Angular 2 filter/search list
HTML
<input [(ngModel)] = "searchTerm" (ngModelChange) = "search()"/>
<div *ngFor = "let item of items">{{item.name}}</div>
Component
search(): void {
let term = this.searchTerm;
this.items = this.itemsCopy.filter(function(tag) {
return tag.name.indexOf(term) >= 0;
});
}
Note that this.itemsCopy is equal to this.items and should be set before doing the search.
You have to manually filter result based on change of input each time by keeping listener over input
event. While doing manually filtering make sure you should maintain two copy of variable, one would be original collection copy & second would be filteredCollection
copy. The advantage for going this way could save your couple of unnecessary filtering on change detection cycle. You may see a more code, but this would be more performance friendly.
Markup - HTML Template
<md-input #myInput placeholder="Item name..." [(ngModel)]="name" (input)="filterItem(myInput.value)"></md-input>
<div *ngFor="let item of filteredItems">
{{item.name}}
</div>
Code
assignCopy(){
this.filteredItems = Object.assign([], this.items);
}
filterItem(value){
if(!value){
this.assignCopy();
} // when nothing has typed
this.filteredItems = Object.assign([], this.items).filter(
item => item.name.toLowerCase().indexOf(value.toLowerCase()) > -1
)
}
this.assignCopy();//when you fetch collection from server.
Search by multiple fields
Assuming Data:
items = [
{
id: 1,
text: 'First item'
},
{
id: 2,
text: 'Second item'
},
{
id: 3,
text: 'Third item'
}
];
Markup:
<input [(ngModel)]="query">
<div *ngFor="let item of items | search:'id,text':query">{{item.text}}</div>
Pipe:
import {Pipe, PipeTransform} from '@angular/core';
@Pipe({
name: 'search'
})
export class SearchPipe implements PipeTransform {
public transform(value, keys: string, term: string) {
if (!term) return value;
return (value || []).filter(item => keys.split(',').some(key => item.hasOwnProperty(key) && new RegExp(term, 'gi').test(item[key])));
}
}
One line for everything!