Learn to build AngularJS Custom Filter

August 11, 2015
by Rahil Shaikh

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.
 

Structure

Lets have a look at the skeleton of a filter.
 

Filter skeleton
/** 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 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.

UpperCase filter
app.filter('caps',[function(){
    return function(data){
        return data.toUpperCase();
    }
}]);

 
Here we are taking in the input and than converting it to upper case using javascript’s toUpperCase() function and returning the same.

Example
var app = angular.module('myApp',[]);
app.controller('profileCtrl',[function(){
    this.name = 'Rahil Shaikh';
}])

app.filter('caps',[function(){
    return function(data){
        return data.toUpperCase();
    }
}]);
Using in HTML
<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.

Custom Search 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.

app.js
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.

index.html
<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.

  1. demo.skill, the search query for skill
  2. demo.status, the search input for status

 

Final Application

 

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?

About

Engineer. Blogger. Thinker. Loves programming and working with emerging tech. We can also talk on Football, Gaming, World Politics, Monetary Systems.

Free PDF

Subscribe and get AngularJS Tips PDF. We never spam!
First Name:
Email:

9 comments

  1. Phil
    |

    Great tutorial! Could you please show how to do the same but with multiple dropdowns?

    • |

      Should be similar except you take the search values from drop downs instead of text box.

  2. yu-chia
    |

    Hello ! Its real a good tutorial 🙂
    But I have a question that is can I use this customs filter and same time use the Pagination??
    I mean the list data can be searched by multiple field and cross pages ?
    thank you for reply 🙂

  3. ashu
    |

    Thanks Rahil,

    Hey you can add pagination too ,,but most of the time in case of huge data , need to depend upon server side call and pull records …

    here is the code which you guys are looking

    ……
    …..your code..

    • ashu
      |
      <tr dir-paginate="p in vm.demo | customSearch:vm.skill:vm.status | orderBy : vm.key : vm.AscOrDesc | itemsPerPage:3"></tr>

      <dir-pagination-controls max-size="3" direction-link="true" boundary-links="true" </dir-pagination-controls>
  4. |

    Hi, Awesome tutorial. Is it possible to search the data using a single input box instead of separate input box?

Leave a Comment