Working with Filters in AngularJS
Filters in AngularJS are like data formatters. You could have a currency value stored in a db but want to render it on the UI by formatting it as a double value (with decimals) and prefixing it with currency symbol. This can be achieved using the concept called filters.
Filter plays the role in formatting the expression (value or data) on the UI. Expressions {} are the way to display the value of the model variable in a HTML template. Though filters can also be applied to directives, controllers and services. The article will demonstrate the concept of filters applied to expressions in AngularJS.
Filters are usually applied on expressions in the view template. Let’s look at the below code snippet:
{{acronymValue | uppercase }}
Here, the acronymValue
is a modal variable which is formatted using the filter named uppercase. It converts the expression to uppercase. The expression and the filter is delimited by pipe ‘|’ character. It can be interpreted as the expression being provided as an input to the uppercase filter. The filter named uppercase is one of the built-in AngularJS filter. Some of the other built-in filters are date, number, currency and many more. Let’s quickly see the date filter:
{{orderDate | date: 'MM-dd-yyyy'}}
The above filter formats the order date to be printed in the MM-dd-yyyy format. As you can see from above, the date filter takes an extra argument that specifies the format pattern of the date to be displayed.
How to create custom filter
Though AngularJS contains many useful built-in filters, its often fun to write your own filter. Built-in filters are useful for basic formatting, but more complex or customized formatting can only be achieved by writing your own filter.
angular.module('myApp.controllers', []). controller('MyController', function($scope) { $scope.greet = "hello world"; }); // Filter module angular.module('myApp.filters',[]).filter('capitalize',function(){ return function(str){ return str.charAt(0).toUpperCase() + str.slice(1); } });
The filter()
method is used to write the custom filter. It takes two parameters: name of the filter and the function that conveys what this will filter will do. In the above code, we have created a filter named ‘capitalize’, which will capitalize the first letter of the expression if its an alphabet. The logic of returning the capitalized word is written in a function passed as a second parameter. This function is also called factory function.
The inner function returned from the factory function takes our expression as a parameter. If you recall, expression is provided as an input to the filter. We take this expression value, convert its first letter to uppercase and return the same. The inner function can also take extra parameters, if you need to pass parameter to your filter just like the date filter above.
We can test this filter by writing the following expression as part of view template.
<html lang="en" ng-app="myApp"> ... <body ng-controller="MyController"> <strong>{{greet | capitalize}}</strong> </body> </html>
Let’s write another filter that takes a parameter. We will call this filter as ‘tokenize’. To keep it simple, the tokenize filter will replace the space in the string expression with the delimited character of your choice and return the string. The delimited character will be passed as a parameter to the filter. Check the code below:
angular.module('myApp.filters',[]).filter('tokenize',function(){ return function(str, delimiter){ return str.replace(/\s/g, delimiter); } });
So the ‘hello world’ string will be filtered to ‘hello-world’, as hyphen ‘-‘ is passed as a parameter to the filter. The ‘tokenize’ filter can be used as follows:
{{greet | tokenize: '-'}}
Let’s look at some interesting built-in filters that are used with arrays or lists. These filters are bounded to ng-repeat
directive to filter the list of data items.
Filter: filter
AngularJS has a built-in filter named literally as filter. It filters the data from an array based on the matching text pattern. Here is an example:
angular.module('myApp.controllers', []). controller('MyController', function($scope) { $scope.courses = [{id: 'C4', title: 'Advanced Mathematics'}, {id: 'C2', title: 'Basic Mathematics'}, {id: 'C3', title: 'Advanced Science'}, {id: 'C1', title: 'Basic Science'}]; });
In controller, we create a scoped array named courses
that contains id
and title
as fields. We will loop through this array using ng-repeat
directive and print the elements. Now let’s apply filter ‘filter’ to this array. Suppose you want to display only courses with title that matches what you type in the input field, you could specify a filter like this:
<html lang="en" ng-app="myApp"> ... <body ng-controller="MyController"> Enter course: <input type="text" ng-model="courseTitle" /> <ul> <li ng-repeat="course in courses | filter: {title:courseTitle} "> {{course.id}} {{course.title}} </li> </ul> </body> </html>
As you can see, filter takes a parameter which is in the form of field: value. The field name is title
and the value is passed from the input field as a model variable. The filter is combined with ng-repeat
directive. The resulting output will display only those courses having titles that matches the term.
Filter: orderBy
The orderBy
filter as the name suggests orders the elements in the list. Let’s see how it works:
<ul> <li ng-repeat="course in courses | orderBy: 'id' "> {{course.id}} {{course.title}} </li> </ul>
Taking our existing courses
array, the above code uses orderBy
filter to order course details by course id field. The default sort order is ascending. To make it descending, just prefix it with hyphen ‘-‘ as shown below:
orderBy: '-id'
Filter: limitTo
The limitTo
filter enables you to apply limit to the lists. You may have an array of 20 items but only want to show 5 items then one can make use of limitTo
filter. Here is the example:
<ul> <li ng-repeat="course in courses | limitTo: 2 "> {{course.id}} {{course.title}} </li> </ul>
Again taking the courses
array, we are filtering to show only 2 records
Chaining filters
Filters are applied to expressions. The return value from the filter is an expression itself. Therefore multiple filters can be chained together to arrive at a desired result. Let’s say, if we want our lists ordered by id and restrict it to display only 2 records, we could chain orderBy
and limitTo
. filters. See the example below:
<li ng-repeat="course in courses | limitTo: 2 | orderBy: 'id'"> {{course.id}} {{course.title}} </li>
Filter when chained together becomes an input to the subsequent filter in the chain. The way filters are chained, its order can impact performance. For example, if you have a huge array of data, first restrict the size by calling limitTo
filter and then order it using orderBy
filter and not vice versa. I have taken an example of orderBy
and limitTo
filters to demonstrate chaining, you could actually chain any filters (both built-in and custom) depending on your requirement.
So, when you want to format data, filters are the way to go. Cheers!
Reference: | Working with Filters in AngularJS from our WCG partner Rajeev Hathi at the TECH ORGAN blog. |