Filter array in template Angular2
The most correct way to do this is with an Angular pipe:
template
<span class="todo-count"><strong>{{ (todos | filter : filterFunction).length }}</strong> left</span>
pipe
import {
Injector,
Pipe,
PipeTransform
} from '@angular/core';
@Pipe({
name: 'filter'
})
export class FilterPipe implements PipeTransform {
public constructor(private readonly injector: Injector) {
}
transform(value: Array<any>, callback: any): any {
return value.filter(callback);
}
}
filterFunction in the component controller
filterFunction(t): boolean {
return !t.complete;
}
you can see why not use methods in angular templates here Don't Use Functions Inside Angular Templates and What to Use Instead. For short This is because of the change detection mechanism in Angular. Angular cannot detect whether the result of a function is changed until it runs the function function.
The thing to consider is that the function will be run even though we have the same input data
Make it a function which applies you criteria:
<span class="todo-count"><strong>{{filterValue()}}</strong> left</span>
And in your controller
filterValue() : number
{
return todos.filter(...);
}
I have written a simple Angular pipe that allows you to pass an object or a callback function as a filter.
Please look at the following example:
home.component.ts
@Component({
selector: 'app-home',
templateUrl: './home.component.html',
})
export class HomeComponent {
array = [
{type: 'log', name: 'Log 1'},
{type: 'log', name: 'Log 2'},
{type: 'log', name: 'Log 3'},
{type: 'log', name: 'Log 4'},
{type: 'event', name: 'Event 1'},
{type: 'event', name: 'Event 2'},
{type: 'event', name: 'Event 3'},
{type: 'event', name: 'Event 4'}
];
complexFilter = (item, index) => item.type === 'event' && index % 2 !== 0;
}
home.component.html
<h1>All items</h1>
<div *ngFor="let item of array">
{{item.name}}
</div>
<h1>Only logs</h1>
<div *ngFor="let item of array | dynamicFilter: { type: 'log'}">
{{item.name}}
</div>
<h1>Complex filter</h1>
<div *ngFor="let item of array | dynamicFilter: complexFilter">
{{item.name}}
</div>
The output will be
All items
Log 1
Log 2
Log 3
Log 4
Event 1
Event 2
Event 3
Event 4
Only logs
Log 1
Log 2
Log 3
Log 4
Complex filter
Event 2
Event 4
As you see, you can provide a simple filter object in the template or a complex filter callback function.
You can find the source code of dynamicFilter
pipe here.