How to apply filters to *ngFor? How to apply filters to *ngFor? angular angular

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.