AngularJS Abstractions: Filters

Monday, May 20, 2013

Filters in AngularJS can form a pipeline to format and adapt model data inside a view. The built-in filters for AngularJS are date (format a date), filter (select a subset of an array), currency (format a number using a currency symbol for the current locale), and many more. I say filters can form a pipeline because you place them inside expressions in a view using a pipe symbol. The canonical example of a filter is the filter filter, which in the following markup filters a list of items according to what the user types in the search input (try it live here).

<input type="search" placeholder="Filter" ng-model="searchTerm"/>    

<ul ng-repeat="item in items | filter:searchTerm | limitTo:maxItems">
    <li>{{item}}</li>
</ul>

Notice the output of filter is also piped to a limitTo filter, which restricts the number of items in the list to maxItems (where maxItems would need to be defined in the model).

Custom Filters

Custom filters only require a filter function to be registered with Angular. The filter function returns a function that will perform the actual work. For example, a plurify filter to add the letter s to the output:

(function() {

    var plurify = function() {
        return function(value) {
            return value + "s";
        };
    };

    angular.module("patientApp.Filters")
           .filter("plurify", plurify);
}());

Now plurify is available to use in a view:

<ul ng-repeat="item in items | filter:searchTerm | limitTo:maxItems">
    <li>{{item | plurify }}</li>
</ul>

A filter can also take one or more optional parameters.

var plurify = function() {
    return function(value, strength) {          
       strength = strength || 1;
       return value + Array(strength + 1).join("s");
    };
};

Now we can add 5 s characters to the output:

<li>{{item | plurify:5 }}</li>

The beauty of filters is how you can package up small pieces of testable code to make the job of the model and view a bit easier, and the syntax to use a filter is easy and intuitive.


Comments
gravatar eric rohlfs Monday, May 20, 2013
I noticed you are using anonymous functions to keep global state clean. I tried this approach but could not get unit tests to work. Any thoughts or tips?
gravatar Scott Monday, May 20, 2013
@Eric: I have a post coming up on this topic in a bit, but for now here is a gist: https://gist.github.com/anonymous/5612709. It is a bit trickier as you have to use the ng injector to get a reference to a component, or use a angular-mocks.js (https://github.com/angular/angular.js/blob/master/src/ngMock/angular-mocks.js)
gravatar Ido Ran Friday, May 24, 2013
Hi, I follow your series if post on Angular and they are simply great. I do think you can go into more details about the parameter that can be passed to the filter beside the value. AFAIK it can be simple, object or function. This can be great extension for filters to make them flexible and powerful. Thanks again for the posts, Ido
gravatar Scott Monday, May 27, 2013
@Ido - I agree, thanks for pointing that out!
Comments are now closed.
by K. Scott Allen K.Scott Allen
My Pluralsight Courses
The Podcast!