Angular 1.x has filters. Angular 2 has pipes, which fulfill a similar purpose. However, there are some key filters in Angular 1.x, such as the "filter filter", that don’t have an equivalent Angular 2 feature. This post details how to build a filter pipe in Angular 2.

Angular 1.x

In Angular 1.x, we define an input box for a user to enter filter text. We then filter a list of items by that text with one simple clause as shown below:

<div class="row">

<div class="col-md-2">Filter by:</div>

<div class="col-md-4"><input type="text" ng-model="listFilter" /></div>

</div> <div class="table-responsive">

<table class="table">

<tbody>

<tr ng-repeat="movie in vm.movies | filter : {title:listFilter}">

<td>{{ movie.title}}</td>

<td>{{ movie.director }}</td>

<td>{{ movie.mpaa | uppercase}}</td>

</tr>

</tbody>

</table>

</div>

Easy breezy.

Angular 2

Angular 2 provides pipes for this same purpose. But with no "filter" pipe in Angular 2, we have to build our own pipe component.

Converting the above code into Angular 2 results in:

<div class="row">

<div class="col-md-2">Filter by:</div>

<div class="col-md-4"><input type="text" #listFilter (keyup)="0" /></div>

</div> <table class="table">

<tbody>

<tr *ngFor="#movie of movies | movieFilter:listFilter.value" >

<td>{{ movie.title}}</td>

<td>{{ movie.director }}</td>

<td>{{ movie.mpaa | uppercase}}</td>

</tr>

</tbody>

</table>

Hmmm. That does not look that different!

A few things you’ll notice here:

The local variable, listFilter, is now prefixed with a hash symbol (#) to explicitly identify it as a local variable. This variable defines an HTML element, so to obtain the value, we need to access listFilter.value.

The (keyup)="0" syntax sets up an event listener for the keyup event. There is no event handler needed for this event, so it is just set to "0".

The filter clause is defined here as movieFilter and we are filtering on the value of the listFilter variable. So our custom pipe is used just like the built-in pipes.

The key is creating the movieFilter pipe. In Angular 1.x, the "filter filter" was built in. In Angular 2, there are some built-in filters, but not a general list filter. So we need to build our own.

The purpose of a pipe is to take in a value, filter that value, and return the filtered result. In this example, the value we are taking in is a list of movies. We filter the movies to only those with a title containing the user-entered text. And we return the filtered result.

Here is the code for the movieFilter. The description follows.

import {Pipe, PipeTransform} from ‘angular2/core’; @Pipe({

name: ‘movieFilter’

})

export class MovieFilterPipe implements PipeTransform { transform(value: any, args: string[]): any { let filter = args[0].toLocaleLowerCase();

return filter ? value.filter(movie=> movie.title.toLocaleLowerCase().indexOf(filter) != -1) : value;

}

}

1) First we import the Pipe and PipeTransform. This is required to build any pipe.

2) We define a Pipe decorator. This tells Angular that this code is a pipe component. And we give the pipe a name: movieFilter. This is the name used in the HTML as part of a template expression.

3) We create a class that provides the processing for our pipe. We export the class so it can be imported by our movie component. And we implement the PipeTransform interface for our tooling. Note that implementing this interface is optional. With the @Pipe decorator, Angular already expects to find a transform method.

4) The PipeTransform interface requires implementing a transform method. This method has two parameters:

value: The value being filtered. In our example, this is the list of movies.

args: An optional array of parameters, one for each parameter passed to the pipe. In our example, we are passing listFilter.value.

5) We then define a result array which will contain the movies that match the filter criteria.

6) We create a variable to hold the passed in parameter. We use toLocaleLowerCase() so that the filtering won’t be case sensitive.

7) We check the filter variable. If there is no filter defined, we simply return the original value. No need to iterate the list. Otherwise we use the JavaScript filter function to filter the list and return it.

NOTE: This code could be simplified using regular expressions.

Lastly, we need the component:

import {Component} from ‘angular2/core’;

import {MovieFilterPipe} from ‘../common/movieFilter.pipe’ @Component({

selector: ‘mh-movie-list’,

templateUrl: ‘app/movies/movieListView.html’,

styleUrls: [‘node_modules/bootstrap/dist/css/bootstrap.css’],

pipes: [MovieFilterPipe]

})

export class MovieListComponent {

…

}

This is the component associated with the movie list view. The two critical steps for the pipe are:

1) Import the MovieFilterPipe.

2) Identify the pipe using the @Component decorator’s pipes array. This provides the list of all custom pipes available for the template.

For more information on Angular 1.x vs Angular 2, see "Angular 1.x to Angular 2 Quick Reference".

For a sample application, see "Angular: 3 Flavors" which has the same application in Angular 1.x, Angular 1.x with TypeScript, and Angular 2.

Enjoy!