angularjssortingfilterpagination

How to do paging in Angular manually


I was searching for really long, and I only found third party solutions for paging, I want an easy to understand solution that I can easily implement.


Solution

  • I found the solution at this link, but I also modified it to suit my liking, it is not as perfect as third party solutions but I found this to be easy to understand for people who wanted to implement paging on thier own This example includes filtering and sorting as well

    var app = angular.module('myApp', []);
    
    app.filter('pagination', function () {
        return function (input, start) {
            start = +start;
            return input.slice(start);
        };
    });
    
    app.controller('myCtrl', ['$scope', function (scope) {
    
        //Initialize scope variables
        scope.pageSize = 5;
        scope.devices = [{ "Id": 1, "DeviceName": "Iphone 6", "DeviceType": "Mobile", "Status": "Available" },
            { "Id": 2, "DeviceName": "Hp Pavillion", "DeviceType": "Tablet", "Status": "Available" },
            { "Id": 3, "DeviceName": "Mi Note 4", "DeviceType": "Mobile", "Status": "Available" },
            { "Id": 4, "DeviceName": "Nexus Tablet 4", "DeviceType": "Tablet", "Status": "Available" },
            { "Id": 5, "DeviceName": "HTC T12", "DeviceType": "Tablet", "Status": "Available" },
            { "Id": 6, "DeviceName": "HTC One", "DeviceType": "Mobile", "Status": "UnAvailable" },
            { "Id": 7, "DeviceName": "One Plus", "DeviceType": "Mobile", "Status": "UnAvailable" },
            { "Id": 8, "DeviceName": "Dell Inspirion", "DeviceType": "Mobile", "Status": "UnAvailable" },
            { "Id": 9, "DeviceName": "Micromax Canvas", "DeviceType": "Mobile", "Status": "UnAvailable" },
            { "Id": 10, "DeviceName": "redmi2", "DeviceType": "Mobile", "Status": "Available" },
            { "Id": 11, "DeviceName": "Gionee2", "DeviceType": "Mobile", "Status": "UnAvailable" }];;
        scope.sortType = 'Username';
        scope.sortReverse = false;
        //Paging
        scope.curPage = 0;
    
        scope.numberOfPages = function () {
          if(scope.pageSize == null){
            scope.pageSize = 1;
            }
            return Math.ceil(scope.devices.length / scope.pageSize);
        };
    
        scope.range = function (n) {
            if (isNaN(n)) {
                n = 0;
            }
            return new Array(n);
        };
    
        scope.setCurrentPage = function (n) {
            scope.curPage = n;
        };
    
    }]);
    <html >
    <head>
        <!-- Angular -->
       <script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.4.5/angular.min.js"></script>
        <!-- Bootstrap -->
      <link rel="stylesheet"     href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.6/css/bootstrap.min.css" integrity="sha384-1q8mTJOASx8j1Au+a5WDVnPi2lkFfwwEAa8hDDdjZlpLegxhjVME1fgjWPGmkzs7" crossorigin="anonymous">
    
      <link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.6/css/bootstrap-theme.min.css" integrity="sha384-fLW2N01lMqjakBkx3l/M9EahuwpSfeNvV63J5ezn3uZzapT0u7EYsXMjQV+0En5r" crossorigin="anonymous">
    
        
    </head>
    <body ng-app="myApp" ng-controller="myCtrl">
    <section id="sectionGrid" ng-cloak>
    
                <div class="table table-bordered table-striped top-buffer text-center" ng-if="devices.length <= 0"> No Data Added.</div>
                <table class="table table-bordered  table-striped top-buffer" style="table-layout: auto; vertical-align: inherit;" ng-show="devices.length >= 1">
                    <thead>
                      <tr>
                        <td >  Items per page</td>
                        <td colspan="2">
                            <input type="number" placeholder="No of Items per page" class="form-control" min="1" pattern="^(0|[1-9][0-9]*)$" ng-model="pageSize" />
                        </td>
                    </tr>
                        <tr>
                            <th class="text-center">
                                <a ng-click="sortType = 'DeviceName' ;sortReverse = !sortReverse ">
                                    Device Name
                                    <span ng-show="sortType == 'DeviceName' && !sortReverse" class="glyphicon glyphicon-menu-down"> </span>
                                    <span ng-show="sortType == 'DeviceName' && sortReverse" class="glyphicon glyphicon-menu-up"> </span>
                                </a>
                                <input type="text" placeholder="Filter" style="width:100%;" class="form-control" ng-model="txtFilterText.DeviceName" />
                            </th>
                            <th class="text-center">
                                <a ng-click="sortType = 'DeviceType' ;sortReverse = !sortReverse ">
                                    Device Type
    
                                    <span ng-show="sortType == 'DeviceType' && sortReverse" class="glyphicon glyphicon-menu-down"> </span>
                                    <span ng-show="sortType == 'DeviceType' && !sortReverse" class="glyphicon glyphicon-menu-up"> </span>
                                </a>
                                <input type="text" placeholder="Filter" style="width:100%;" class="form-control" ng-model="txtFilterText.DeviceType" />
                            </th>
                            <th class="text-center">
                                <a ng-click="sortType = 'Status' ;sortReverse = !sortReverse ">
                                    Status
    
                                    <span ng-show="sortType == 'Status' && sortReverse" class="glyphicon glyphicon-menu-down"> </span>
                                    <span ng-show="sortType == 'Status' && !sortReverse" class="glyphicon glyphicon-menu-up"> </span>
                                </a>
                                <input type="text" placeholder="Filter" style="width:100%;" class="form-control" ng-model="txtFilterText.Status" />
                            </th>
    
                        </tr>
                    </thead>
                    <tbody>
                        <tr ng-click="selected = !selected" ng-class="{customSelect:selected}" ng-repeat="x in devices  | filter : txtFilterText | orderBy:sortType:sortReverse  | pagination: curPage * pageSize | limitTo: pageSize ">
                            <td class="text-center">{{ x.DeviceName }}</td>
                            <td class="text-center">{{ x.DeviceType }}</td>
                            <td class="text-center">{{ x.Status }}</td>
                        </tr>
                    </tbody>
                    <tfoot>
                        <tr>
                            <td colspan="10" class=" text-center">
                               <div ng-disabled="devices.length >= 1" class=" btn-group">
                                <button type="button" class="btn btn-default" ng-disabled="curPage == 0"
                                        ng-click="setCurrentPage(0)">
                                    First
                                </button>
                                <button type="button" class="btn btn-default" ng-disabled="curPage == 0"
                                        ng-click="setCurrentPage(curPage-1)">
                                    Prev
                                </button>
    
                                <span class="btn btn-file btn-info disabled">Page {{curPage + 1}} of {{ numberOfPages() }}</span>
    
                                <button type="button" class="btn btn-default"
                                        ng-disabled="curPage >= devices.length/pageSize - 1"
                                        ng-click="setCurrentPage(curPage+1)">
                                    Next
                                </button>
                                <button type="button" class="btn btn-default"
                                        ng-disabled="curPage >= devices.length/pageSize - 1"
                                        ng-click="setCurrentPage(numberOfPages() - 1)">
                                    Last
                                </button>
    
                            </div>
                                <hr />
                                <div class="btn-group">
                                    <button type="button" class="btn btn-default" ng-disabled="curPage == {{$index}}" ng-repeat="x in range(numberOfPages()) track by $index"
                                            ng-click="setCurrentPage($index)">
                                        {{$index + 1}}
                                    </button>
                                </div>
                            </td>
                        </tr>
                    </tfoot>
                </table>
            </section>
      </body>
    </html>

    Let me explain,

    1. I have used a custom filter to splice the list to required length, then in the controller, I have initialized the "pageSize" variable which can be set dynamically or can be static as per your application requirement.
    2. I have given "devices" array static data but again it can also be set dynamically
    3. The sorting is done with "sortType" and "sortReverse" variables.
    4. The "numberOfPages" function calculates the amount of pages based on your data and your "pageSize" variable
    5. The "setCurrentPage" sets the value of "curPage".
    6. The "range" function just returns an array of number returned from "numberOfPages" function to create individual buttons for paging.

    Hope you find this solution useful.