Angular Filters

Angular Filters

Angular filters are a convenient and simple way to format data in your application. Oftentimes, the values you use in code are not formatted for your users’ eyes. Whether they are currency values or dates, you need to process this data into a human-readable format.

Angular filters excel at formatting data. They are also used to process arrays to display collections of UI elements sorted, filtered, or paged. They are very powerful and with much power comes great responsibility.

This post covers what filters are, how they work, and general guidance to use them. For specific usage instruction for the built-in filters, the Angular docs do a very good job. Now it’s time to look at the basics.

Filter Basics

For those that didn’t read the last post on expressions, filters process the result of an expression before it is rendered. A simple example is formatting a number as currency.

Filter scenarios are generally simple input and output, but filters also accept parameters. In the case of formatting a currency, the built-in currency filter accepts a string parameter to change the currency symbol as well as a parameter to denote how many decimal places to display.

The syntax for filters is straightforward. After the expression you wish to filter, use the pipe character | to declare the filter. To set parameters, follow the filter name with a colon : and add the parameter value. Each subsequent parameter value is separated by a colon :. Using the built-in currency filter looks like this:

{{ vm.number | currency : '€' : 0 }}

The default currency filter displays the input with a currency symbol, commas to separate the thousand and million places, and also rounds the value to two decimal places. This example uses two parameters to change the currency symbol and to remove the decimals entirely.

In addition to the formatting advantages, the currency filter also rounds the decimal places. For instance using the above example, the value 999.9 displays €1,000 whereas 999.4 displays €999 – nice!

When using parameters, the order is important. For instance, if you want to leave the default currency symbol but also want to limit the decimal places to 0, you still have to pass the symbol as a parameter.

Another nice feature is chaining. You can chain multiple filters to format a single value. For instance if you want a date format with all uppercase letters, you can use two filters together.

{{ vm.date | date : 'MMMM d, yyyy' | uppercase }}

It’s important to note that the order matters. Processing flows from the leftmost filter to the right and subsequent filters can overwrite the processing done by a previous filter.

Preprocess Filters for Performance

When using a filter within a binding expression, it is loaded in the DOM. While the syntax is convenient, the performance implications can add up. To get a better understanding of how filters and expressions affect UI performance, read Todd Motto’s post on Angular performance. The important thing to remember is that anytime you add a piece of Angular code to your markup, you are adding processing to the $digest cycle. This $digest cycle runs repeatedly whenever a binding is changed in the UI and the amount of processing can easily increase by an order of magnitude depending on how you choose to write your expressions, bindings, directives, and filters.

For this reason, consider using filters within a controller or service of your application where it runs outside of the scope of the DOM and on-demand when needed instead of linked to the $digest cycle. Use the built-in $filter service to call a filter from a controller or service.

vm.preprocessCurrency = $filter('currency')(vm.number, '€', 0);

In this example, vm is the scope object in the controller. The $filter service is injected as a parameter to the controller function. If you understand how to use a filter in markup, using the $filter service in the controller is similar. First, pass the filter name as a string to the $filter service. Invoking this service returns the filter function which is why it is followed by a second invocation to process the data. The filter function’s first parameter is the data to filter, vm.number, followed by any other parameters. In this case, the currency symbol and the amount of decimal places are passed to the filter function.

This plunker demonstrates the two different filter approaches in action.

Anatomy of Custom Filters

Under the covers, filters are relatively simple JavaScript objects. Similar to other Angular objects, they are created with the angular.Module object.

angular
    .module('app', [])
    .filter('kittens', function () {

        return function (data, exclamations) {

            var kittens = 'Ooh, Kittens';
            exclamations = typeof exclamations !== 'number' ? 1 : exclamations;

            for (var i = 0; i < exclamations; i++) {
                kittens = kittens + '!';
            }

            return kittens;
        };
    });

The kittens filter converts any input into the value Ooh, Kittens! with an optional parameter to set the number of exclamation points (admittedly, probably only useful for this post). This is an example using the filter in markup.

{{ vm.someValue | kittens : 5 }}

To create the filter, use the module’s filter method which accepts a string representing the filter name as the first argument and a factory function as the second argument. The filter name must be a valid expression identifier and cannot contain any special characters, periods ., or hyphens -.

The factory function is a function that returns a new instance of the filter function. Because filters should be stateless, the factory function helps to ensure that output values are consistent, otherwise wreaking havoc on the $digest cycle. The factory function can also accept other dependencies as arguments.

This plunker demonstrates the custom filter.

Filtering it Down

Angular filters are a convenient and simple feature of the Angular framework. They help you format and process data in the view. They are flexible in that you can use them within controllers or services to preprocess data. And, you can write your own custom filters to re-use throughout your application.

Again, be sure to check out how to use the built-in filters in the Angular documentation. If there’s anything else you wanted to know about filters, please leave a comment. This post was created because an interested reader left a comment. Thanks Mariusz for the idea.

2 thoughts on “Angular Filters”

  1. I read your tutorials on first angular project in visual studio, expressions, filters. I will be grateful if you can write something on services.

Leave a Reply

Your email address will not be published. Required fields are marked *