One of the coolest features AngularJS has come up with are Filters. Filters are prominently used to modify the value of expression for display.
In this tutorial we will learn to create custom filters in AngularJS, then we will build two custom filters, first one would be a simple one that would convert any string to uppercase. In the second example we will see how to use $filters on arrays, we will build a search filter that will take multiple search queries. This type of search filter was also request by our reader Don Cistaro in our previous articles here.
AngularJS provides lots of built in filters that are handy but sometimes are not enough for our needs. Hence comes the concept of custom filters.
DEMO DOWNLOAD
The great thing about Angular filter is that they can be used directly in the HTML binding or inside the controller. AngularJS provides a $filter API to create custom filters just like how we would declare controllers. So lets dive deep and learn how to create an AngularJS custom filter.
Table of Contents
ToggleStructure
Lets have a look at the skeleton of a filter.
/** filter takes in two parameters
@filterName and a
@function that returns another function **/
app.filter('myFilter', function() {
/** the inner function does all the processing**/
/** take one required parameter the data and multiple optional parameters **/
return function(input, optional1, optional2) {
//process input
return output;
}
});
The filter takes in two parameters, the name of the filter and a function that returns another function. The inner function is responsible for processing the data and returning it in the desired format. The inner function takes original data as a parameter and multiple optional parameters.
Â
Now that we have seen the structure of the filter lets create some custom filters.
Uppercase Filter
Lets start off with a simple filter that will change any string to Upper Case.
app.filter('caps',[function(){
return function(data){
return data.toUpperCase();
}
}]);
var app = angular.module('myApp',[]);
app.controller('profileCtrl',[function(){
this.name = 'Rahil Shaikh';
}])
app.filter('caps',[function(){
return function(data){
return data.toUpperCase();
}
}]);
<body ng-app="myApp">
<div ng-controller="profileCtrl as profile">
<p>{{profile.name|caps}}</p>
</div>
</body>
We just looked at a simple example how filters can be used for simple things. Lets take another example but this time a bit more complex and on arrays. Lets build a custom filter to allow user to search with multiple queries.
Custom filter to Search with multiple queries
We will build a filter that will allow a user to search through a set of data. Although this won’t be a regular search, we will enable the user to enter multiple queries and return the result based on it.
For example, there is a list of employees that shows the employee skill along with his status. The user can search this set and find the employee say having skill set of ‘MEANStack’ and is on ‘BENCH’ (Not assigned to any project.)
Lets first have a look at the filter.
//filter name customSearch
app.filter('customSearch',[function(){
/** @data is the original data**/
/** @skill is the search query for skill**/
/** @status is the search query for status**/
return function(data,skill,status){
var output = []; // store result in this
/**@case1 if both searches are present**/
if(!!skill && !!status){
skill = skill.toLowerCase();
status = status.toLowerCase();
//loop over the original array
for(var i = 0;i<data.length; i++){
// check if any result matching the search request
if(data[i].skill.toLowerCase().indexOf(skill) !== -1 && data[i].status.toLowerCase().indexOf(status) !== -1){
//push data into results array
output.push(data[i]);
}
}
} else if(!!skill){ /**@case2 if only skill query is present**/
skill = skill.toLowerCase();
for(var i = 0;i<data.length; i++){
if(data[i].skill.toLowerCase().indexOf(skill) !== -1){
output.push(data[i]);
}
}
} else if(!!status){ /**@case3 if only status query is present**/
status = status.toLowerCase();
for(var i = 0;i<data.length; i++){
if(data[i].status.toLowerCase().indexOf(status) !== -1){
output.push(data[i]);
}
}
} else {
/**@case4 no query is present**/
output = data;
}
return output; // finally return the result
}
}]);
Our filter is named as customSearch. The inner function takes in 3 parameters the original data, skill search string and status search string. On an overview we loop over the original array and based on the values of skill and status we compute and return our output. Please read my comments inline within the above code to see what is happening on each step.
Â
Now lets build an example app that will show the usage of our customSearch filter.
var app = angular.module('angularTable', []);
app.controller('demoCtrl',function($http){
var vm = this;
vm.users = []; //declare an empty array
$http.get("mockJson/mock.json").success(function(response){
vm.users = response; //ajax request to fetch data into vm.data
});
});
//filter name customSearch
app.filter('customSearch',[function(){
/** @data is the original data**/
/** @skill is the search query for skill**/
/** @status is the search query for status**/
return function(data,skill,status){
var output = []; // store result in this
/**@case1 if both searches are present**/
if(!!skill && !!status){
skill = skill.toLowerCase();
status = status.toLowerCase();
//loop over the original array
for(var i = 0;i<data.length; i++){
// check if any result matching the search request
if(data[i].skill.toLowerCase().indexOf(skill) !== -1 && data[i].status.toLowerCase().indexOf(status) !== -1){
//push data into results array
output.push(data[i]);
}
}
} else if(!!skill){ /**@case2 if only skill query is present**/
skill = skill.toLowerCase();
for(var i = 0;i<data.length; i++){
if(data[i].skill.toLowerCase().indexOf(skill) !== -1){
output.push(data[i]);
}
}
} else if(!!status){ /**@case3 if only status query is present**/
status = status.toLowerCase();
for(var i = 0;i<data.length; i++){
if(data[i].status.toLowerCase().indexOf(status) !== -1){
output.push(data[i]);
}
}
} else {
/**@case4 no query is present**/
output = data;
}
return output; // finally return the result
}
}]);
We have defined our Angular module and a simple controller that fetches data from a static JSON file. Importantly we have also added our customFilter to our app.
In your markup include the necessary files, declare ng-app and ng-controller. We will need two input boxes for our search queries and a table that displays the list using ng-repeat.
<div ng-app="angularTable">
<div class="bs-component" ng-controller="demoCtrl as demo">
<label >Search BY</label>
<input type="text" ng-model="demo.skill" class="form-control" placeholder="Search by Skill">
<label >AND </label>
<input type="text" ng-model="demo.status" class="form-control" placeholder="Search by Status">
<table class="table table-striped table-hover">
<thead>
<tr>
<th>Id</th>
<th>Name</th>
<th>Skill</th>
<th>Status</th>
</tr>
</thead>
<tbody>
<tr ng-repeat="user in demo.users|customSearch:demo.skill:demo.status">
<td>{{user.id}}</td>
<td>{{user.first_name}}</td>
<td>{{user.skill}}</td>
<td>{{user.status}}</td>
</tr>
</tbody>
</table>
</div>
</div>
If you observe above in the ng-repeat syntax we have added our customSearch filter which takes in 2 arguments.
- demo.skill, the search query for skill
- demo.status, the search input for status
Conclusion
Here we learned how to build custom filters from scratch. We created two custom filters and learnt how to use them. AngularJS Filter is a powerful tool for manipulating data for presentation. Filters are unique as they can be used on both UI and in controllers unlike services. Are there any cool custom filters that you’ve came across?