AngularJS offers a few built-in filters that were described in one of my previous articles. Mostly, they format data. A number of them is not big. It is pretty small while a range of filters needed in modern applications is quite wide. Fortunately, there is no reason to complain about it too much. A developer can easily create a filter that he/she needs. This article describes how to create a custom filter and use it.
A filter is a function that takes an input and statelessly produces an output in a deterministic way. It means that the result should not depend on how many times the filter has been executed before.
No parameter filter
For purpose of this post, I will create a filter for converting temperature values between Celsius degrees and Fahrenheit degrees.
A filter is created by executing the filter function on an Angular module. See the below example:
<div ng-app="testApp">
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.4.0/angular.min.js" type="text/javascript"></script>
<script type="text/javascript">
// app.js
angular.module('testApp', [
]);// filters.js
angular.module('testApp')
.filter('celsius', [function() {
return function(celsius) {
if (celsius === undefined || celsius === null) {
return '';
}
return celsius + '°C';
};
}])
.filter('fahrenheit', [function() {
return function(celsius) {
if (celsius === undefined || celsius === null) {
return '';
}
var farenheit = celsius * 1.8 + 32;
return farenheit + '°F';
};
}]);
</script>
<input type="number" ng-model="temperature" />
<p>{{temperature}}</p>
<p>{{temperature | celsius}}</p>
<p>{{temperature | fahrenheit}}</p>
</div>
{{temperature}}
{{temperature | celsius}}
{{temperature | fahrenheit}}
There are two filters defined above: celsius and fahrenheit. The first one returns the original value with a unit (°C) added. The second one converts the provided value and returns it with a unit (°F). The filters are used in the same way as Angular built-in filters. The original value for further calculation is passed to the filter as the first parameter of the function.
Custom filter with parameter
The above example does not cover all cases. A filter can be parametrized like the currency filter.
<p>{{3456.7843 | currency:"€":0}}</p> <!-- €3,457 -->
Similar effect can be achieved very easily by adding more arguments to the function in the filter. For example two above filters: celsius and fahrenheit can be replaced by one - temp with a parameter targetUnit that can be celsius or fahrenheit.
<div ng-app="testApp">
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.4.0/angular.min.js" type="text/javascript"></script>
<script type="text/javascript">
// app.js
angular.module('testApp', [
]);// filters.js
angular.module('testApp')
.filter('temp', [function() {
return function(celsius, targetUnit) {
if (celsius === undefined || celsius === null) {
return '';
}
switch(targetUnit) {
case 'celsius':
return celsius + '°C';
break;
case 'fahrenheit':
return celsius * 1.8 + 32 + '°F';
break;
default:
return '';
}
}
}]);
</script>
<input type="number" ng-model="temperature" />
<p>{{temperature}}</p>
<p>{{temperature | temp:'celsius'}}</p>
<p>{{temperature | temp:'fahrenheit'}}</p>
</div>
{{temperature}}
{{temperature | temp:'celsius'}}
{{temperature | temp:'fahrenheit'}}
A value that is provided after the colon goes to the filter function as the second argument. The first one is the original value.
Filters are powerful feature of AngularJS. A list of those that are built-in is small enough that sooner or later a need of one or more additional ones becomes true. Luckily, implementing them is very easy and the code still stays well-organized.