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.