How to apply filters to *ngFor?
Basically, you write a pipe which you can then use in the *ngFor
directive.
In your component:
filterargs = {title: 'hello'};items = [{title: 'hello world'}, {title: 'hello kitty'}, {title: 'foo bar'}];
In your template, you can pass string, number or object to your pipe to use to filter on:
<li *ngFor="let item of items | myfilter:filterargs">
In your pipe:
import { Pipe, PipeTransform } from '@angular/core';@Pipe({ name: 'myfilter', pure: false})export class MyFilterPipe implements PipeTransform { transform(items: any[], filter: Object): any { if (!items || !filter) { return items; } // filter items array, items which match and return true will be // kept, false will be filtered out return items.filter(item => item.title.indexOf(filter.title) !== -1); }}
Remember to register your pipe in app.module.ts
; you no longer need to register the pipes in your @Component
import { MyFilterPipe } from './shared/pipes/my-filter.pipe';@NgModule({ imports: [ .. ], declarations: [ MyFilterPipe, ], providers: [ .. ], bootstrap: [AppComponent]})export class AppModule { }
Here's a Plunker which demos the use of a custom filter pipe and the built-in slice pipe to limit results.
Please note (as several commentators have pointed out) that there is a reason why there are no built-in filter pipes in Angular.
A lot of you have great approaches, but the goal here is to be generic and defined a array pipe that is extremely reusable across all cases in relationship to *ngFor.
callback.pipe.ts (don't forget to add this to your module's declaration array)
import { PipeTransform, Pipe } from '@angular/core';@Pipe({ name: 'callback', pure: false})export class CallbackPipe implements PipeTransform { transform(items: any[], callback: (item: any) => boolean): any { if (!items || !callback) { return items; } return items.filter(item => callback(item)); }}
Then in your component, you need to implement a method with the following signuature (item: any) => boolean, in my case for example, I called it filterUser, that filters users' age that are greater than 18 years.
Your Component
@Component({ ....})export class UsersComponent { filterUser(user: IUser) { return !user.age >= 18 }}
And last but not least, your html code will look like this:
Your HTML
<li *ngFor="let user of users | callback: filterUser">{{user.name}}</li>
As you can see, this Pipe is fairly generic across all array like items that need to be filter via a callback. In mycase, I found it to be very useful for *ngFor like scenarios.
Hope this helps!!!
codematrix
Simplified way (Used only on small arrays because of performance issues. In large arrays you have to make the filter manually via code):
See: https://angular.io/guide/pipes#appendix-no-filterpipe-or-orderbypipe
@Pipe({ name: 'filter'})@Injectable()export class FilterPipe implements PipeTransform { transform(items: any[], field : string, value : string): any[] { if (!items) return []; if (!value || value.length == 0) return items; return items.filter(it => it[field].toLowerCase().indexOf(value.toLowerCase()) !=-1); }}
Usage:
<li *ngFor="let it of its | filter : 'name' : 'value or variable'">{{it}}</li>
If you use a variable as a second argument, don't use quotes.