In last post, we saw how Angular JS helps us in two-way data binding. As I mentioned earlier, Angular JS offers much more than just data binding. We will explore the filtering and sorting features offered by Angular JS.
Angular has a set of filters defined to display data to the user in certain format. We can create our own filters if we are not happy with any of the existing filter. Check Angular’s official developer guide to know more about what filters offer. In this post we will see the usage of some of the built-in filters.
I continue with the same data as I used in the last post. Here is the Angular JS controller with data that we will use in this post. We will add some members to the controller later in the post:
Filtering
Data in an array can be filtered using Angular JS in two ways.
In one approach, we can filter data irrespective of the attributes. The filter is applied across the data in an array. Following markup shows it:
Initially, the table will display all items present in the items array. As we type some text in the text box, data in the array will be filtered based on the entered text and the filtered data will immediately appear on the list.
As you observe, we didn’t ask Angular to filter data based on a property. This is a general filter. It is applied across the properties.
To filter data based on a property, we have to make some changes to the filter specified above. Following markup segment shows how to do it:
Text entered in the first text box will be used to filter data irrespective of property; it behaves just as our previous case. But the text entered in the second text box will be used to filter data by name alone.
Since price is a dollar amount, we can display the value with a dollar symbol using currency filter.
Sorting
Data in an array can be sorted based on values of a property. We can do it using the orderBy filter.
Let’s add a drop down list to the above sample and sort data based on the selected property. Following markup demonstrated this:
As soon as a property is selected from drop-down, you will see the data in the table displayed is sorted according to that property. Observe the sorting pattern of numeric columns (Price and Quantity). They are sorted like strings, not like numbers. This is the default behaviour of the orderBy filter, as mentioned in the documentation.
This behaviour can be overridden by defining a function. If we return value in the form of integer from this function, orderBy filter will apply numeric sorting. Following function can be used to sort string and integer type values. It has to be added to controller:
Replace sortExpression of orderBy filter with mySortFunction to sort Price and Quantity as numbers.
The mySortFunction checks if the value passed is a number. If it is not a number, it returns the value as is. Otherwise, it parses the value as integer and returns the value.
You can play with the sample on jsfiddle: Happy coding!
Angular has a set of filters defined to display data to the user in certain format. We can create our own filters if we are not happy with any of the existing filter. Check Angular’s official developer guide to know more about what filters offer. In this post we will see the usage of some of the built-in filters.
I continue with the same data as I used in the last post. Here is the Angular JS controller with data that we will use in this post. We will add some members to the controller later in the post:
function ShoppingCartCtrl($scope) { $scope.items = [ {Name: "Soap", Price: "25", Quantity: "10"}, {Name: "Shaving cream", Price: "50", Quantity: "15"}, {Name: "Shampoo", Price: "100", Quantity: "5"} ]; }
Filtering
Data in an array can be filtered using Angular JS in two ways.
In one approach, we can filter data irrespective of the attributes. The filter is applied across the data in an array. Following markup shows it:
Search: <input type="text" ng-model="searchText" /> <table border="1"> <thead> <tr> <th>Name</th> <th>Price</th> <th>Quantity</th> </tr> </thead> <tbody> <tr ng-repeat="item in items | filter:searchText"> <td>{{item.Name}}</td> <td>{{item.Price}}</td> <td>{{item.Quantity}}</td> </tr> </tbody> </table>
Initially, the table will display all items present in the items array. As we type some text in the text box, data in the array will be filtered based on the entered text and the filtered data will immediately appear on the list.
As you observe, we didn’t ask Angular to filter data based on a property. This is a general filter. It is applied across the properties.
To filter data based on a property, we have to make some changes to the filter specified above. Following markup segment shows how to do it:
Search by any: <input type="text" ng-model="search.$" /> Search by name: <input type="text" ng-model="search.Name" /> <table border="1"> <thead> <tr> <th>Name</th> <th>Price</th> <th>Quantity</th> </tr> </thead> <tbody> <tr ng-repeat="item in items | filter:search"> <td>{{item.Name}}</td> <td>{{item.Price}}</td> <td>{{item.Quantity}}</td> </tr> </tbody> </table>
Text entered in the first text box will be used to filter data irrespective of property; it behaves just as our previous case. But the text entered in the second text box will be used to filter data by name alone.
Since price is a dollar amount, we can display the value with a dollar symbol using currency filter.
<td>{{item.Price | currency}}</td>
Sorting
Data in an array can be sorted based on values of a property. We can do it using the orderBy filter.
Let’s add a drop down list to the above sample and sort data based on the selected property. Following markup demonstrated this:
<div>Sort by: <select ng-model="sortExpression"> <option value="Name">Name</option> <option value="Price">Price</option> <option value="Quantity">Quantity</option> </select> </div> <table border="1"> <thead> <tr> <th>Name</th> <th>Price</th> <th>Quantity</th> </tr> </thead> <tbody> <tr ng-repeat="item in items | orderBy:sortExpression | filter:search"> <td>{{item.Name}}</td> <td>{{item.Price | currency}}</td> <td>{{item.Quantity}}</td> </tr> </tbody> </table>
As soon as a property is selected from drop-down, you will see the data in the table displayed is sorted according to that property. Observe the sorting pattern of numeric columns (Price and Quantity). They are sorted like strings, not like numbers. This is the default behaviour of the orderBy filter, as mentioned in the documentation.
This behaviour can be overridden by defining a function. If we return value in the form of integer from this function, orderBy filter will apply numeric sorting. Following function can be used to sort string and integer type values. It has to be added to controller:
$scope.mySortFunction = function(item) { if(isNaN(item[$scope.sortExpression])) return item[$scope.sortExpression]; return parseInt(item[$scope.sortExpression]); }
Replace sortExpression of orderBy filter with mySortFunction to sort Price and Quantity as numbers.
<tr ng-repeat="item in items | orderBy:mySortFunction | filter:search">
The mySortFunction checks if the value passed is a number. If it is not a number, it returns the value as is. Otherwise, it parses the value as integer and returns the value.
You can play with the sample on jsfiddle: Happy coding!
Thanks a lot for your mySortFunction. This is the solution I was looking for. Great job! It will fix a bug in my next release (https://github.com/boxplayer/eTuneBook).
ReplyDeleteMartin,
DeleteYou are welcome. I am glad that you could use this learning in your project.
post how to use $filter in controller
ReplyDeleteSure Vignesh, give me some time
DeleteI just posted the article: http://sravi-kiran.blogspot.in/2013/12/InvokingAngularJsFiltersFromController.html
DeleteCan you show me how i can do that filter inside my controller ?
ReplyDeleteReally awesome.. It helped me a lot.
ReplyDeleteCan you please let me know if it is possible to sort ascending or descending on each column when we click on coulumn header ? Can you please give one example ?
Thanks in advance
This comment has been removed by the author.
ReplyDeleteThis comment has been removed by the author.
ReplyDeleteHi, thanks for sharing, how can i check if the filtered item doesn't exist?
ReplyDeleteThis comment has been removed by the author.
ReplyDeleteif i will use this
ReplyDelete{{items[$index].Name}}
{{items[$index].Price | currency}}
{{items[$index].Quantity}}
instead of
{{item.Name}}
{item.Price | currency}}
{{item.Quantity}}
Then how to sort? pls post the technique! i am waiting..
Filter is not working. How to do it? I am not able to find the cause.
ReplyDeletehow to filter price in descending order?
ReplyDeleteThank you for posting this! I have been searching for over an hour on this topic, and your post is the easiest to understand! Great example :)
ReplyDeleteI need to bold the matched filtered text in table. How can I do that??
ReplyDeleteUse ng-class in your element e.g:
Deleteng-class="{'class-to-add':filtered-expression}"
=)