I have the below data object:
goods = [ { name: 'Canon', title: 'Canon EOS 5D Mark III Body', tags: ['tag1','tag2','tag3']}, { name: 'Nikon', title: 'Nikon D3100', tags: ['tag1','tag4','tag5']}, { name: 'Sony', title: 'Sony CX700', tags: ['tag2','tag3','tag6']}, { name: 'Fujifilm', title: 'Fujifilm XT20',tags: ['tag1','tag4','tag5']}, { name: 'Sony', title: 'Sony CX500', tags: ['tag3','tag4','tag5']}, { name: 'Nikon', title: 'Nikon D750', tags: ['tag1','tag5','tag6']}, ];
And a html page with 2 select boxes.
<select [(ngModel)]="selectedTag1" (change)="valueSelected1()"> <option *ngFor="let item of tagName">{{ item }}</option> </select> <select [(ngModel)]="selectedTag2" (change)="valueSelected2()"> <option *ngFor="let item of tagName">{{ item }}</option> </select> <div *ngFor="let item of goods"> <app-goods [goodsData]="item"></app-goods> </div>
In my ts file I would like to filter the tags array for selectedTag1, selectedTag2 or Both. i am not sure how to filter the array (do I need to loop through it?) AND I do not know how to combine the 2 filters (do I need combineLatest from RXJS?). I have the below so far
ngOnInit() { this.tagName = this.dropdownService.brandName; this.goods = this.goodsService.goods; }; public valueSelected1() { this.goods = this.goodsService.goods.filter(item => item.tags[0] === this.selectedTag1); console.log(this.selectedTag1); } public valueSelected2() { this.goods = this.goodsService.goods.filter(item => item.tags[0] === this.selectedTag1); console.log(this.selectedTag2); }
I think I need to loop through the array here item.tags[0]
but not sure of the best way to do it and then do a combineLatest.. Maybe not? I have created a stackBlitz
Advertisement
Answer
You can do this in one of many number of ways:
- With a getter
get goodsFiltered(): any[] { return this.goods?.filter(({ tags }) => tags.indexOf(this.selectedTag1) !== -1 && tags.indexOf(this.selectedTag2) !== -1) ?? []; }
- With a custom pipe (the best way imho)
import { Pipe, PipeTransform } from '@angular/core'; @Pipe({ name: 'filteredGoods' }) export class FilteredGoodsPipe implements PipeTransform { transform(goods: any[], { tag1, tag2 }): any[] { return goods.filter(({ tags }) => tags.indexOf(tag1) !== -1 && tags.indexOf(tag2) !== -1); } }
<div *ngFor="let item of goods | filteredGoods: { tag1: selectedTag1, tag2: selectedTag2 }"> <app-goods [goodsData]="item"></app-goods> </div>
- Directly in your
change
event callbacks:
public valueSelected1() { this.goods = this.goods.filter(({ tags }) => tags.indexOf(this.selectedTag1) !== -1 && tags.indexOf(this.selectedTag2) !== -1); } public valueSelected2() { this.goods = this.goods.filter(({ tags }) => tags.indexOf(this.selectedTag1) !== -1 && tags.indexOf(this.selectedTag2) !== -1); }
Hope this helps 🙂
Edit: I can’t tell what types things have, but if this.goodsService.goods
is an Observable
, you should pipe the filter operator:
ngOnInit() { this.tagName = this.dropdownService.brandName; this.goods = this.goodsService.goods.pipe( filter(({ tags }) => tags.indexOf(this.selectedTag1) !== -1 && tags.indexOf(this.selectedTag2) !== -1) ); }