Home > Enterprise >  How to create Pipe to filter NgFor with two condition?
How to create Pipe to filter NgFor with two condition?

Time:04-08

I want to filter a list with two condidition, name and eventId, so I created a pipe to filter the result of my ngFor.

...
 <input matInput placeholder="Digite algo a ser apresentado..." [(ngModel)]="filteredString" />
...

and I have my ngFor

<div *ngFor="let element of dataSource?.data?.content | filter: filteredString ">
...
</div>

this Is the pipe that I created

 transform(value: any, filterString:string) {
      if(value === undefined  || value === null) return value;

      return value.filter(function(element) { 
          return element.name.toLowerCase().includes(filterString.toLocaleLowerCase());
      })
  }

It's working with the name of the property, but I have only on input and I need to work too with the eventId, or maybe any property.

CodePudding user response:

you can add more arguments to your pipe like this:

 transform(value: any, filterString:string, id?: number) {
      // use the id
      if(value === undefined  || value === null) return value;

      return value.filter(function(element) { 
          return element.name.toLowerCase().includes(filterString.toLocaleLowerCase());
      })
  }

and then feed it:

<div *ngFor="let element of dataSource?.data?.content | filter: filteredString : eventId ">

but I would caution generally against using a pipe for filtering as it performs poorly and can be buggy. if you don't treat the array and its elements as immutable, and something in the array changes, the pipe will not update unless the pipe is marked impure which will cause it to evaluate on every change detection cycle.

a better approach is to use observables to filter your array, ideally with reactive forms to give even greater control over filtering which can be a heavy operation.

my preferred implementation looks like this:

in template

 <input matInput placeholder="Digite algo a ser apresentado..." [formControl]="filterCtrl" />

...

<div *ngFor="let element of filtered$ | async ">

in component:

filterCtrl = new FormControl('');
filterString$ = this.filterCrl.valueChanges.pipe(
  // whatever operators you need to control this stream, these are common ones
  debounceTime(300),
  distinctUntilChanged(),
  startWith('')
)

// not sure what your data source actually looks like but this is an observable that emits your array when / if it changes
filtered$ = combineLatest(this.dataSrc$, this.filterString$).pipe(
  map(([data, filterString]) => 
    data.content.filter(element => element.name.toLowerCase().includes(filterString.toLocaleLowerCase())
  )
)
  • Related