Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

pipe inside child component not called when input changed

I have a custom pipe to filter an array. The pipe is used inside a child component, data to child component is passed through input parameter. When the input data is changed, pipe is not called. Is there anything I have to do differently when using ChangeDetectionStrategy.OnPush inside child component.

Edit

In the example below, product-list-container gets products from ngrx store. The data is passed into product-list component through input parameter.

In product-list component, i have a filter that is for filtering out rows based on some criteria. The issue I am seeing is that, when input value changes pipe function is not called. Pipe is getting called only once on component load.

@Component({
  selector: 'product-list-container',
  template: `
    <app-product-list [productList]="productList$ | async"></app-product-list>
  `
})
export default class ProductListContainer implements OnInit {
  public productList$: Observable<Product[]>;
  constructor(public store: Store<AppState>) {
  }
  ngOnInit() {
    this.productList$ = this.store.select('productList');
  }
}

@Component({
  selector: 'app-product-list',
  template: `
    <div *ngFor="let product of productList | filterActiveProduct">
   // More code here 
    </div>
  `,
  changeDetection: changeDetectionStrategy.onPush
})
export default class ProductList {
  @Input() productList: Product[];
  constructor() {
  }
}

@Pipe({
  name: 'fromNow'
})
export class filterActiveProduct {
  transform(products: Product[], args: Array<any>): string {
    return products.findAll(p => p.isActive);
  }
}

Thanks,

like image 945
Yousuf Avatar asked Oct 24 '25 04:10

Yousuf


1 Answers

that because your pipe is Pure pipes.

Angular executes a pure pipe only when it detects a pure change to the input value. A pure change is either a change to a primitive input value (String, Number, Boolean, Symbol) or a changed object reference (Date, Array, Function, Object).

Angular ignores changes within (composite) objects. It won't call a pure pipe if we change an input month, add to an input array, or update an input object property.

using Impure pipes in your case:

Angular executes an impure pipe during every component change detection cycle. An impure pipe will be called a lot, as often as every keystroke or mouse-move.

With that concern in mind, we must implement an impure pipe with great care. An expensive, long-running pipe could destroy the user experience.

FilterActiveProduct:

@Pipe({
  name: 'filterActiveProduct',
  pure: false
})
export class FilterActiveProduct {}

ProductList:

@Component({
  selector: 'app-product-list',
  template: `
    <div *ngFor="let product of productList | filterActiveProduct">
   // More code here 
    </div>
  `,
})
export default class ProductList {
  @Input() productList: Product[];
  constructor() {
  }
}

Following this document page: https://angular.io/docs/ts/latest/guide/pipes.html

like image 145
Tiep Phan Avatar answered Oct 26 '25 17:10

Tiep Phan