Pagination with Filtering using AngularJS

17. September 2015 AngularJS 10

In the previous post we take a look at how to enable pagination on a web page using AngularUI. Things gonna be different when have filters applied on your ng-repeat. The pagination would not update itself as the filter applied.

What you need to do is add a watch the textbox which the filtration is based on and bind the ng-repeat to the filtered list.

Please refer to the previous post to learn how to enable the basic pagination on your web page.

1. Inject the AngularJS filter filter into your controller:

app.controller(‘MainCtrl’, function ($scope, filterFilter)

To inject a filter in AngularJS we need to postfix it with “Filter”. We are injecting angularJS filter filter. If you have your custom filter performing the filtration you need to inject it into your controller.

2. Add a watch to the text box which the filtration is based on:

$scope.$watch('search.name', function (term) {
    var obj = { name: term }

    $scope.filterList = filterFilter($scope.list, obj);
    $scope.currentPage = 1;
});

We add a watch on the name property of our search object. If only you watch the search object, the watch will only be triggered once when the object is created. Subsequent changes on the name property would not be triggered the watch.

The function argument term contains the new text whenever user types something.

Notice that we are creating an object and assign the term to its name property. We can pass a literal value, or an object to the filter. If we only pass the term to the filter, it will search that term in all properties of the object and filter the list. In this case our interest is to only filter the name property of our object, hence we create an object and assign the term to it name property.

Finally we set the current page to the first page.

3. Bind the ng-repeat to the filtered list:

<div ng-repeat="item in filterList | start: (currentPage - 1) * pageSize | limitTo: pageSize" />

Notice that we have removed the filtering from the ng-repeat.

<div ng-repeat="item in filterList | filter: search | start: (currentPage - 1) * pageSize | limitTo: pageSize" />

Full source:

Demo

<html>
<head>
    <title>AngularJS Pagination Sample</title>
    <script src="Scripts/angular.min.js"></script>
    <script src="Scripts/angular-ui/ui-bootstrap-tpls.min.js"></script>
    <link href="Content/bootstrap.min.css" rel="stylesheet" />
    <meta charset="utf-8" />

    <script>
        (function () {
            var app = angular.module('paging-app', ['ui.bootstrap']);

            app.controller('MainCtrl', function ($scope, filterFilter) {
                $scope.list = [];

                $scope.pageSize = 5;

                $scope.init = function () {
                    for (var i = 0; i < 100; i++) {
                        $scope.list.push({ name: 'name ' + i, key: 'key ' + i });
                    }
                };

                $scope.$watch('search.name', function (term) {
                    var obj = { name: term }

                    $scope.filterList = filterFilter($scope.list, obj);
                    $scope.currentPage = 1;
                });
            })

            .filter('start', function () {
                return function (input, start) {
                    if (!input || !input.length) { return; }

                    start = +start;
                    return input.slice(start);
                };
            });

        }());
    </script>
</head>
<body ng-app="paging-app">
    <br />
    <div class="container" ng-controller="MainCtrl" ng-init="init()">
        <div>
            <input type="text" class="form-control" placeholder="Search" ng-model="search.name" />
            <br />
        </div>
        <div>
            <div ng-repeat="item in filterList | start: (currentPage - 1) * pageSize | limitTo: pageSize" 
                 class="alert alert-success col-md-12">
                <span ng-bind="item.name"></span>
            </div>
            <pagination total-items="filterList.length" items-per-page="pageSize" ng-model="currentPage" max-size="5" class="pagination-sm"></pagination>
        </div>
    </div>
</body>
</html>

10 thoughts on “Pagination with Filtering using AngularJS”

  • 1
    Jonathan on February 7, 2016 Reply

    thanks man.

    why if use a table instead span items filter not working
    Eg::

    {{ item.name }}

    i search name “textNotFound” and clear input dont show items again.

    • 2
      Behnam on March 1, 2016 Reply

      It doesn’t matter whether you are using a table or span. You are controlling your model in AngularJS. The View is just representing the model no matter it is a table or span. Can you paste the snippet of where your ng-repeat is and the pagination tag as well?

  • 3
    Craig on March 18, 2016 Reply

    Great article. However, I am also using a dropdown with an ng-model, which should filter using the value of the selected option against a client id.

    Can’t seem to work out how to combine the two filters, as the filterList array is defined/overwritten each time.

    Any ideas?

    Thanks

    • 4
      Behnam on April 1, 2016 Reply

      Thanks for your comment Craig and sorry for delay replying you, I was traveling.

      Regarding the filtration you need $watch an object rather just one property.
      For instance instead of:
      $scope.$watch(‘search.name’, function (term) { …

      You should do:
      $scope.$watch(‘search’, function (term) { …

      Where your “search” is an object that a textbox will set search.name and your dropdown will set search.clientId.
      Give it a try and let me know the result.

  • 5
    Partha Chowdhury on August 9, 2016 Reply

    Hi buddy,
    Thanks for sharing good stuff. I have used your stuff but it’s not working. The reason is the version problem of “ui-bootstrap-tpls.min.js”. In my app the version is (already it is totally built and i can not want to change it) 1.3.3. and in your example version – 0.13.4 been used. So is there any way to get it working only for the pagination. Although besides this the filtration is working quite well.

    Thanks

    • 6
      Behnam on August 9, 2016 Reply

      Hi Partha, thanks for outlining this.
      In the current version of ui.bootrstrap, they changed the attribute and tag names from the version I’ve used.
      So what you should do to make this sample work, is only change this:
      <pagination total-items...></pagination>
      Into this:
      <ul uib-pagination total-items=...></ul>

  • 7
    Olof on November 15, 2016 Reply

    Thanks for the article!
    Can I change the filter so it searches for an exact word, instead of part of a word? I cant find any documentation about filterList, do you know some?

    • 8
      Behnam on November 28, 2016 Reply

      $scope.filterList is a scope variable we’ve defined which is the result of filtering the ‘$scope.list’. About your second question I will do a search and will let you know.

  • 9
    sagili ramanareddy on June 6, 2018 Reply

    HI Behnam,

    Thanks for great artical.
    Kindly consider my requirement as well, same way we have implemented like gmail deletion is not working.
    1.For example original table is having 1000 records i am going delete all the records using checkboxall (topmost check box) its working fine.
    2.when ever i am searching related to “103.122. ” its returning 120 records out of 1000 but while i was selecting topmost checkbox like checkbox all its deleting all 1000 records.
    can you help me how can i achive this.

  • 10
    sagili ramanareddy on June 6, 2018 Reply

    HI …
    Thanks for great artical.
    Kindly consider my requirement as well, same way we have implemented like gmail deletion is not working.
    1.For example original table is having 1000 records i am going delete all the records using checkboxall (topmost check box) its working fine.
    2.when ever i am searching related to “103.122. ” its returning 120 records out of 1000 but while i was selecting topmost checkbox like checkbox all its deleting all 1000 records.
    can you help me how can i achive this.

Leave a Reply

Your email address will not be published. Required fields are marked *

This site uses Akismet to reduce spam. Learn how your comment data is processed.