AngularJS Data Handling: Filters and Reusability Techniques

In my previous article, I described the AngularJs Data Binding & Controllers. You can read it from the following link.

AngularJS - Data Binding & Controllers: Part 4

If you have been using Angular for a while now, you might have felt the need to do similar things several times and sometimes in several controllers. In my early days, I had nothing much to do about it. I used to declare similar functions under the scope of multiple controllers, that were meant to do the same task, thus repeating the code. It never felt right, though.

Then I was introduced to the filters. Why don't I just walk this talk? Let's take an instance where we need to reverse a variable string. What I would earlier do, is declare a function under the scope of the controller. Something like.

function oneCtrl($scope) {
    $scope.message = "Shashank";
    $scope.reversed = function (message) {
        return message.split("").reverse().join("");
    };
}

And use it in HTML-like.

<div ng-controller="oneCtrl">
    <input type="text" ng-model="message"/>
    <h1>{{ reversed(message) }}</h1>
</div>

Find this example working at jsfiddle

But then, what is the use of AngularJS that boasts a code re-usability feature if I need to write this reversed() method in every controller? Reasonable doubt!

AngularJS has filters in store for this. What it suggests is something like this.

myApp.filter("reverse", function() {
    return function(text) {
        return text.split("").reverse().join("");
    };
});

And use it in your HTML like this.

<div ng-controller="oneCtrl">
    <input type="text" ng-model="message"/>
    <h1>{{ message | reverse }}</h1>
</div>

Yes, this is the syntax for applying a filter. Using a pipe '|' followed by the name of the filter.

Find it working here jsfiddle

AngularJS

ngFilter

Now that we have learned to create our custom filters, I should not forget to mention the predefined filters by Angular available for our use.

I'll use a big JSON object to present the data, on which we'll apply the filters. This object will be returned by a service. For instance.

myApp.factory("Avengers", function() {
    var Avengers = {};
    Avengers.cast = [
        {
            name: 'Robert Downey Jr.',
            character: 'Tony Stark / Iron Man'
        },
        {
            name: 'Samuel L. Jackson',
            character: 'Nick Fury'
        }
    ];
    return Avengers;
});
function avengersCtrl($scope, Avengers) {
    $scope.avengers = Avengers;
};

So having defined the Avengers model from the service into our scope, let's move on to the HTML part.

<body ng-app="myApp">
    <div ng-controller="avengersCtrl">
        <table>
            <tr ng-repeat="actor in avengers.cast">
                <td>{{ actor.name }}</td>
                <td>{{ actor.character }}</td>
            </tr>
        </table>
    </div>
</body>

You may notice the ng-repeat attribute here, which is a very powerful one, it helps us to loop through every item of a list, or an object. Before we start filtering, let's see this example working jsfiddle

Let's set up a search box now to filter the results of this object into the table. Just make these additions to the code inside the "avangersCtrl".

<div ng-controller="avengersCtrl">
    <input type="text" ng-model="search"/>
    <table>
        <tr ng-repeat="actor in avengers.cast | filter: search">
            <td>{{ actor.name }}</td>
            <td>{{ actor.character }}</td>
        </tr>
    </table>
</div>

We are all set. This will help you to filter results based on the keywords you type into the search box.

Additionally, to filter the results only by a specific key, like name or character only, just replace the model with.

<input type="text" ng-model="search.name"/>

And now the results will only be based on the names present in the list that match the keyword you type in. See the working example here jsfiddle

Other Built-in filters

Angular provides us with certain built-in filters that can be of great use and several of them can be stacked up on the same list.

For Instance

<tr ng-repeat="actor in avengers.cast | orderBy: 'name'">

Will sort the results by name in ascending order. This order can be reversed by.

<tr ng-repeat="actor in avengers.cast | limitTo: 5">

Will return only the first five results from the list. To get the last five results, just do.

<tr ng-repeat=”actor in avengers.cast | limitTo: -5” />  

Awesome right? Moreover

{{ actor.name | lowercase }}

will convert all the characters of this string to lowercase, for uppercase, use.

{{ actor.name | uppercase }