I use angular 6 and I would like to filter the results of an async pipe, before rendering them in the UI.
Here is my code right now
this.results = this.form.get('name').valueChanges.pipe(
filter(formdata => formdata.name.length > 0),
switchMap( formdata => this.service.getNames(formdata.name))
);
and the template
<div *ngIf='results | async ; let items'>
<div *ngFor='let item of items'>{{item.id}} {{item.name}} </div>
</div>
From the pipe I get some ids and names. I already have an array of ids. I would like to filter the ids of the pipe and not render the ones that are already in the array.
So, here is what I try to do.
array = [{id:1,name:'one'},{id:2,name:'two'}];//I already have this
new version of filter in pipe
this.results = this.form.get('name').valueChanges.pipe(
filter(formdata => formdata.name.length > 0),
switchMap( formdata => this.service.getNames(formdata.name)) ,
filter(checkIfResultIdInArray())//pseudocode
);
Assume that checkIfResultIdInArray
is I function I created. Filters and returns all the ids that are not in the array
. So the ids/names that end up in the template are not the {id:1,name:'one'},{id:2,name:'two'}
.
Or maybe I can filter in the template somehow?
@Davy's answer is what I would do myself. However another option is to use a pipe. This is the way to go if you would like to reuse this functionality.
@Pipe({name:'filterOnId'})
export class FilterOnIdPipe implements PipeTransform {
transform(list : MyObject[], acceptedIds : number[]){
return list.filter(item => acceptedIds.indexOf(item.id) > -1);
}
}
and in the template
<div *ngFor='let item of results | async | filterOnId : acceptedIds'>
{{item.id}} {{item.name}}
</div>
Note the following:
You use your custom pipe the same way you use built-in pipes. You must include your pipe in the declarations array of the AppModule If you choose to inject your pipe into a class, you must provide it in the providers array of your NgModule.
As suggested in the comments, you can replace AsyncPipe
by a regular array, or alter the value of the emitted value (@Davy's solution is good).
There is however a template based solution. I'm putting it here for those who don't want to merge component's logic with view display.
component
result$ = of([1,2,3,4,5,6,7,8]); // for the sake of example
isAcceptedThing(thing){
return thing%2 != 0 // accept only odd numbers
}
template
<ul >
<ng-container *ngFor="let thing of result$ | async">
<li *ngIf="isAcceptedThing(thing)">
filtered thing = {{ thing }}
</li>
</ng-container>
</ul>
Output
- filtered thing = 1
- filtered thing = 3
- filtered thing = 5
- filtered thing = 7
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With