How to filter elements inside a ngFor loop based on an object’s property string

I need to filter the elements inside the ngFor loop by changing the category in the drop-down list. Therefore, when a certain category is selected from the list, it should only list items containing the same category.

HTML template:

 <select> <option *ngFor="let model of models">{{model.category}}</option> </select> <ul class="models"> <li *ngFor="let model of models" (click)="gotoDetail(model)"> <img [src]="model.image"/> {{model.name}},{{model.category}} </li> </ul> 

Array Element:

 export var MODELS: Model[] = [ { id: 1, name: 'Model 1', image: 'img1', category: 'Cat1', }, { id: 2, name: 'Model 2', image: 'img2', category: 'Cat3', }, { id: 3, name: 'Model 3', image: 'img3', category: 'Cat1', }, { id: 4, name: 'Model 4', image: 'img4', category: 'Cat4', }, ... ]; 

In addition, the drop-down list contains duplicate category names. To do this, you need to specify only unique categories (lines).

I know that creating a custom channel would be the right way, but I don't know how to write it.

Plunker: http://plnkr.co/edit/tpl:2GZg5pLaPWKrsD2JRted?p=preview

+7
string filter angular typescript ngfor
source share
1 answer

Here is an example pipe:

 import { Pipe, PipeTransform } from '@angular/core'; @Pipe({ name: 'matchesCategory' }) export class MathcesCategoryPipe implements PipeTransform { transform(items: Array<any>, category: string): Array<any> { return items.filter(item => item.category === category); } } 

To use it:

 <li *ngFor="let model; of models | matchesCategory:model.category" (click)="gotoDetail(model)"> 

===== for example plunkr ====

You need your favorite changes to reflect in some variable

First define a member in your class:

 selectedCategory: string; 

then update your template:

 <select (change)="selectedCategory = $event.target.value"> <option *ngFor="let model of models ">{{model.category}}</option> </select> 

last, use the channel:

  <li *ngFor="let model; of models | matchesCategory:selectedCategory" (click)="gotoDetail(model)"> 

==== comments after viewing the plunger ====

I noticed that you used the promise. Angular2 is more focused on rxjs. So, the first thing I changed is your service, replace:

 getModels(): Promise<Model[]> { return Promise.resolve(MODELS); } 

to:

 getModels(): Observable<Array<Model>> { return Promise.resolve(MODELS); } 

and

 getModels(id: number): Observable<Model> { return getModels().map(models => models.find(model.id === id); } 

then in ModelsComponent

 models$: Observable<Array<Model>> = svc.getModels(); uniqueCategories$: Observable<Array<Model>> = this.models$ .map(models => models.map(model => model.category) .map(categories => Array.from(new Set(categories))); 

Your parameters will become:

  <option *ngFor="let category; of uniqueCategories$ | async">{{model.category}}</option> 

and your list:

  <li *ngFor="let model; of models$ | async | matchesCategory:selectedCategory" (click)="gotoDetail(model)"> 

This is a very difficult decision, since you have a lot of duplicates, and you continue to request this service. Take this as a starting point and request the service only once, then derive specific values ​​from the result.

If you want to save the code, just implement UniqueValuesPipe, its conversion will receive a single parameter and will filter it to return unique categories using Array.from(new Set(...)) . You will need to at least first match it with strings (categories).

+12
source share

All Articles