Raghav
Raghav

Reputation: 1229

How to filter based on property value in an array of objects in Angular2?

I have an input text that takes the area as show below:

<input type="text" [(ngModel)]="areaSearch">

And, i have a list to filter based on the entered area against area_name property

<ul *ngIf="areaSearch">
    <li *ngFor="let area of areaList | filter : {area_name: areaSearch} ">
        ...
    </li>
</ul>

Am getting error like The pipe 'filter' could not be found. Can anyone help me to solve this?..

Upvotes: 3

Views: 19982

Answers (2)

Sajeetharan
Sajeetharan

Reputation: 222657

Angular does not have concept named filter, instead you should create your custom pipe as follows,

import { Pipe, PipeTransform } from '@angular/core';
@Pipe({name: 'filterByArea'})
export class FilterByStatusPipe implements PipeTransform {

    transform(areaList : any, areaname: string): any[] {
        if (areaList) {
            return areaList.filter((listing: any) => listing.area_name === areaname);
        }
    }
}

and use it as follows,

<ul *ngIf="areaSearch">
    <li *ngFor="let area of areaList | filterByArea:areaSearch">
        ...
    </li>
</ul>

Upvotes: 10

BeetleJuice
BeetleJuice

Reputation: 40946

I would define filteredAreaList in the component as a readonly:

// this goes in the component
get filteredAreaList() {
    return this.areaList.filter(v => v.area_name === this.areaSearch)
}

This will ensure that filteredAreaList has only those elements of areaList whose area_name property matches the current areaSearch

Then in the template, just iterate over filteredAreaList

<ul *ngIf="areaSearch">
    <li *ngFor="let area of filteredAreaList ">
        ...
    </li>
</ul>

One benefit of this approach is that the logic is kept out of the template, and it is easy to extend (e.g: if in the future the displayed list depends on other component properties). I also like the pipe solution from Sajeetharan.

UPDATE: 2019-05-17

With nearly 2 more yrs of Angular under my belt since I wrote my answer, I have a slightly new perspective upon reading mine and Sajeetharan's accepted response. My solution has less overhead; it is also easier to implement; there are fewer steps -- no need to create a pipe, declare it in a module, make sure the component's module also has access to it etc. However Sajeetharan's solution will run faster especially if areaList is a big array because by default the pipe logic is only run if the inputs change.

This means that in practice once the user enters an area name, the filter will execute just once and be done, whereas with my solution, the filteredAreaList getter will execute every change detection cycle. The difference is trivial if you have only a few dozen areas, but if you have a very large set it matters.

Upvotes: 4

Related Questions