'How to call pipe only on value change
I am using angular 2 with primeng p-dropdown and have a case where I need to filter a child dropdown when the user selects a parent. I did it using a custom pipe like
<p-dropdown [options]="carTypesOptions" [(ngModel)]="CarTypeId" name="CarTypeId"></p-dropdown>
<p-dropdown [options]="carMakeOptions | filterCarMakes: CarTypeId" [(ngModel)]="CarMakeId" name="CarMakeId"></p-dropdown>
So when user selects a car type, I am filtering the second dropdown by using the filterCarMakes pipe which takes the CarTypeId (parent selected id). It all works great. Here's my filterCarMakes pipe.
@Pipe({
name: 'filterCarMakes',
pure: false
})
export class FilterMakesPipe implements PipeTransform {
transform(carMakesOptions: CarMakeSelectItem[], carTypeId: string): CarMakeSelectItem[] {
if (!carTypeId)
return carMakesOptions.filter(p => p.carTypeId == null);
//perform some filtering operation
return filteredCarMakeOptions;
}
}
The issue is if I put a console.log in the pipe, it would continue to log that message on console very quickly (like once every 100ms) which means it will continue to call even if the value of parent does not change. The side effect of this is, I can't select any value in child dropdown if there's a scroll because it continues to refresh the options.
Simple screenshot of filtered dropdown is below (it won't let me scroll to select other values and will continue to refresh)
P.S: I don't want to do it in onChange event and calling the pipe from component, so is it possible to do it inside template?
Solution 1:[1]
This is happening because the pipe is unpure
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).
Impure pipes: Angular executes an impure pipe during every component change detection cycle. An impure pipe is called often, as often as every keystroke or mouse-move.
Source: https://angular.io/guide/pipes
but if you really need your pipe to be impure for any reason, for performance concerns you will need to set the component changeDetection strategy to OnPush, and trigger change detection manually when the changes are applied.
import { Component, ChangeDetectionStrategy, ChangeDetectorRef } from '@angular/core';
@Component({
selector: 'awesome-component',
templateUrl: './pda.html',
changeDetection: ChangeDetectionStrategy.OnPush
})
export class AwesomeComponent implements OnInit {
constructor(
private cd: ChangeDetectorRef,
) { }
...
fetchData() {
...
// after any data change
this.cd.markForCheck();
...
}
...
}
Sources
This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.
Source: Stack Overflow
| Solution | Source |
|---|---|
| Solution 1 | Community |

