Sunday 21 April 2019

Search Sort and Pagination in ng-repeat – AngularJS


In any web application to display data,  we often use tables or lists. When working with angular applications you will use ng-repeat to display the data in tables or lists.
However when the data items get large, our table must-have features such as searchsort and pagination. These features will make your application more user-friendly and tables more manageable. This AngularJS tutorial will show you how to implement search, sort, and Pagination in your Angular applications.
Note: This is a tutorial for Angular 1, if you are looking for implementation in Angular 2 visit this tutorial

Roadmap

For our demo application, we will first display the data using ng-repeat. Next, we will start implementing the three features one by one starting with the easiest first.
  1. Display data using ng-repeat
  2. Implement search in AngularJS( filter )
  3. Implement sort in AngularJS( orderBy )
  4. Implement pagination in AngularJS( dirPaginate )

Watch Video



Setup

First lets set up our files.
We have included angular.js and app.js to our index.html. Then we have declared our angular app as ng-app="angularTable" and controller as ng-controller="listdata". We have also included some bootstrap css files.
INDEX.HTML
<!doctype html>
<html lang="en" ng-app="angularTable">
  <head>
    <meta charset="utf-8">
    <title>Search Sort and Pagination in Angular js</title>
    <link rel="stylesheet" type="text/css" href="css/bootstrap.min.css">
    <link rel="stylesheet" type="text/css" href="css/styles.css">
  </head>
  <body>
    <div role="main" class="container theme-showcase">
      <div class="" style="margin-top:90px;">
        <div class="col-lg-8">
                    <div class="page-header">
                        <h2 id="tables">Search Sort and Pagination in Angular js</h2>
                    </div>
                    <div class="bs-component" ng-controller="listdata"> 
                    </div>
                </div>
      </div>
    </div>
        <script src="https://cdnjs.cloudflare.com/ajax/libs/angular.js/1.5.1/angular.js"></script>
        <script src="app/app.js"></script>
  </body>
</html>
app.js will contain our js code, our angular module and controller. If you see below we have also injected $scope and $http into our controller.
APP.JS
var app = angular.module('angularTable', []);

app.controller('listdata',function($scope, $http){

});
We also have a file as mock.json which contains data in json format. We will make an ajax request using $http and display the data in our markup using ng-repeat.
MOCK.JSON
[{"id":1,"first_name":"Heather","last_name":"Bell","hobby":"Eating"},
{"id":2,"first_name":"Andrea","last_name":"Dean","hobby":"Gaming"},
{"id":3,"first_name":"Peter","last_name":"Barnes","hobby":"Reading Books"},
{"id":4,"first_name":"Harry","last_name":"Bell","hobby":"Youtubing"},
{"id":5,"first_name":"Deborah","last_name":"Burns","hobby":"Fishing"},
{"id":6,"first_name":"Larry","last_name":"Kim","hobby":"Skipping"},
{"id":7,"first_name":"Jason","last_name":"Wallace","hobby":"Football"},
.....,
......,
{"id":25,"first_name":"Russell","last_name":"Patterson","hobby":"Singing"}]

Display data using ng-repeat

To fetch the data we will do a $http request to the mock.json. Next we will take the data into a $scope variable and then using ng-repeat we will display the data.
[adrotate banner=”5″]
Since the data fetched will be an array of objects, ng-repeat will iterate over it.
In your controller.
APP.JS
app.controller('listdata',function($scope, $http){
    $scope.users = []; //declare an empty array
    $http.get("mockJson/mock.json").success(function(response){ 
        $scope.users = response;  //ajax request to fetch data into $scope.data
    });
});
In our markup
ng-repeat="user in users"
This statement will repeat over the users.
INDEX.HTML
....

<div class="bs-component" ng-controller="listdata">
                        <table class="table table-striped table-hover">
                            <thead>
                                <tr>
                                    <th>Id</th>
                                    <th>First Name</th>
                                    <th>Last Name</th>
                                    <th>Hobby</th>
                                </tr>
                            </thead>
                            <tbody>
                                <tr ng-repeat="user in users">
                                    <td>{{user.id}}</td>
                                    <td>{{user.first_name}}</td>
                                    <td>{{user.last_name}}</td>
                                    <td>{{user.hobby}}</td>
                                </tr>
                            </tbody>
                        </table> 
                    </div>

....
We have created a table and then added ng-repeat to iterate on our list of users.

Display data using ng-repeat
Display data using ng-repeat
So far so good.

Implement search feature

Now lets add filtering for the list of users. Adding search in AngularJs is very easy, Angular comes in with lots of awesome builtin filters.
To do this we need to create an input text box where the end-user can type in the keyword and then apply the value of the input model to ng-repeat.
Lets add our search bar just above our table.
INDEX.HTML
    <form class="form-inline">
        <div class="form-group">
            <label >Search</label>
            <input type="text" ng-model="search" class="form-control" placeholder="Search">
        </div>
    </form>
Now we have to filter our
ng-repeat="user in users" with the value of ng-model="search".
After which our ng-repeat statement will look like this.
ng-repeat="user in users|filter:search"
So now the if the end-user types anything in the search bar the search results will instantaneously appear in the table.

search filter
search filter

Implement sort feature

AngularJs provides orderBy filter which takes in two further arguments.
  1. Name of the key to sort with
  2. Order of sort (asc or desc), a Boolean value.
Lets add that to our ng-repeat statement.
ng-repeat="user in users|orderBy:sortKey:reverse|filter:search"
Remember, here orderBy is the filter name and sortKey and reverse are $scope variables. So now to make this work we need to set values of $scope.sortKey and $scope.reverse variables.
To do this we will make our table headers clickable, and call a function in our controller using ng-click. This function will change the sortKeyand reverse based on the table header clicked.
Lets first add sort function to our controller.
APP.JS
    $scope.sort = function(keyname){
        $scope.sortKey = keyname;   //set the sortKey to the param passed
        $scope.reverse = !$scope.reverse; //if true make it false and vice versa
    }
As you can see this function does two things, sets the sortKey variable and reverses the reverse variable.
Time to invoke this function using ng-click. Change your table headers to below.
INDEX.HTML
    <thead>
        <tr>
            <th ng-click="sort('id')">Id</th>
            <th ng-click="sort('first_name')">First Name</th>
            <th ng-click="sort('last_name')">Last Name</th>
            <th ng-click="sort('hobby')">Hobby</th>
        </tr>
    </thead>
Remember the parameter sort() function takes should be the key of that column. The sorting will work now but we should add some indicator in UI so that the user knows sorting is on which column and if it is ascending or descending.
We will use bootstrap glyphicons to show the sort icon. Code that does the trick.
<span class="glyphicon sort-icon" ng-show="sortKey=='id'" ng-class="{'glyphicon-chevron-up':reverse,'glyphicon-chevron-down':!reverse}"></span>
We only want to show the icon on the column that is being sorted, we do that using ng-show="sortKey=='id'", then we use ng-class to change the icon depending upon the value of reverse.
Now your table head should look like this.
INDEX.HTML
    <thead>
        <tr>
            <th ng-click="sort('id')">Id
                <span class="glyphicon sort-icon" ng-show="sortKey=='id'" ng-class="{'glyphicon-chevron-up':reverse,'glyphicon-chevron-down':!reverse}"></span>
            </th>
            <th ng-click="sort('first_name')">First Name
                <span class="glyphicon sort-icon" ng-show="sortKey=='first_name'" ng-class="{'glyphicon-chevron-up':reverse,'glyphicon-chevron-down':!reverse}"></span>
            </th>
            <th ng-click="sort('last_name')">Last Name
                <span class="glyphicon sort-icon" ng-show="sortKey=='last_name'" ng-class="{'glyphicon-chevron-up':reverse,'glyphicon-chevron-down':!reverse}"></span>
            </th>
            <th ng-click="sort('hobby')">Hobby
                <span class="glyphicon sort-icon" ng-show="sortKey=='hobby'" ng-class="{'glyphicon-chevron-up':reverse,'glyphicon-chevron-down':!reverse}"></span>
            </th>
        </tr>
    </thead>

Data sorted by id
Data sorted by id
Woah! Our app just had search and now it has sort, it just keeps on getting better. Time to paginate.

Implement pagination

Although we saw Angular provides built-in filters for searching and sorting but there is nothing as such when it comes to pagination. So what now? Do we need to build the entire pagination logic by our-self? Well, you can do that but there are a few third party libraries that we can use to add pagination. One of them is dirPaginate.
The reason I’m using dirPaginate is because of its features and ease of implementation. By using this you don’t need to write any logic into your controller. Kind of plug and play.

Installation

First thing we need to do is get the dirPaginate library.
If you have used bower you can download it by simply running.
bower install angular-utils-pagination
Or you can download it manually from the below link.
Now include the dirPagination.js in your index.html and add angularUtils.directives.dirPagination as dependency to your module.
<script src="lib/dirPagination.js">&lt/script>
angular.module('angularTable', ['angularUtils.directives.dirPagination']);

Basic settings

Now to paginate your data we can use the dir-paginate directive. This directive will replace the ng-repeat directive in our code. And we will add the itemsPerPage filter which is provided by this library.
itemsPerPage would be the number of items to be displayed per page.
Observe closely the below code.
INDEX.HTML
    <tbody>
        <tr dir-paginate="user in users|orderBy:sortKey:reverse|filter:search|itemsPerPage:5">
            <td>{{user.id}}</td>
            <td>{{user.first_name}}</td>
            <td>{{user.last_name}}</td>
            <td>{{user.hobby}}</td>
        </tr>
    </tbody>
Before adding pagination:
ng-repeat="user in users|orderBy:sortKey:reverse|filter:search"
After adding pagination:
dir-paginate="user in users|orderBy:sortKey:reverse|filter:search|itemsPerPage:5"
Now our table is paginated but we don’t have pagination controls to navigate to different pages. dirPaginate provides dir-pagination-controls to display pagination controls.
Add this just below your table or any where on the page where you want to display.
INDEX.HTML
    <dir-pagination-controls
        max-size="5"
        direction-links="true"
        boundary-links="true" >
    </dir-pagination-controls>
 
Explanation
max-size="5" maximum number of page numbers to show.
direction-links="true" Next page and previous page links true/false
boundary-links="true" First page and last page links true/false
Now we also have pagination in our application. dirPagination comes with more awesome features such as using a custom template for pagination controls, multiple paging per page, page change event etc. Visit the Github page to find out more.

pagination
pagination
I’ve also went ahead and added a bit of custom styling to the application.
STYLE.CSS
.sort-icon {
    font-size: 9px;
    margin-left: 5px;
}

th {
    cursor:pointer;
}

Conclusion

AngularJS has some great built-in features to implement search and sort this tutorial explains how to do that in the simplest possible way, this AngularJS tutorial also explained arguably the easiest way to implement the complicated paginationSearch Sort and Pagination are three things that a client will demand 9 times out of 10 when displaying large tabular data. These features allow ease of use and better the User Experience of your applications. Now that you know, you can add them to your projects.

2 comments:

Angular Tutorial (Update to Angular 7)

As Angular 7 has just been released a few days ago. This tutorial is updated to show you how to create an Angular 7 project and the new fe...