I had created a data pager to use in a knockout / MVC4 project. Recently I adapted it to angular for another ASP.NET/MVC 4 project. I was told this may be useful for the community, so here it is. I will put this up on github soon.
The controller method: Should return a json object that has the following objects in it: TotalRecords, Records. TotalRecords is an int that tells the pager the total number of records in the source that passed the query.
Consuming javascript: Should initiate the pager, and handle the server requests. Here is a snippet that illustrates this:
--------------
Finally, the pager code:
The controller method: Should return a json object that has the following objects in it: TotalRecords, Records. TotalRecords is an int that tells the pager the total number of records in the source that passed the query.
Consuming javascript: Should initiate the pager, and handle the server requests. Here is a snippet that illustrates this:
scope.pager = new pager(); scope.filter = [[someFilterYouPassToControllerMethod]] scope.pager.onGetRecords = function(){ scope.filter.StartRecord = scope.pager.currentBeginRecord; scope.filter.NumRecords = scope.pager.numRecordsPerPage; http({ method: 'GET', url: [[controllerMethodUrl]], params: scope.filter }) .success(function (data) { scope.pager.onRecordsFetched(data); }); };Here is an example of html/ng snippet that renders the pager (uses twitter bootstrap styles and font-awesome):
--------------
<div class="container"> <div class="row"> <div class="col-md-6 form-inline"> <div class="input-prepend input-append"> <div class="btn-group"> <button class="btn btn-default btn-sm" ng-disabled="pager.cannotGoBack()" ng-click="pager.goToBeginning()"><i class="icon-fast-backward"></i></button> <button class="btn btn-default btn-sm" ng-disabled="pager.cannotGoBack()" ng-click="pager.goBack()"><i class="icon-step-backward"></i></button> </div> <input type="text" ng-model="pager.currentPage" class="form-control" ng-model-onblur ng-change="pager.goToPage()" style="width: 54px;" /> <span class="add-on"> / {{pager.totalPages}} pages</span> <div class="btn-group"> <button class="btn btn-default btn-sm" ng-disabled="pager.cannotGoForward()" ng-click="pager.goForward()"><i class="icon-step-forward"></i></button> <button class="btn btn-default btn-sm" ng-disabled="pager.cannotGoForward()" ng-click="pager.goToEnd()"><i class="icon-fast-forward"></i></button> </div> <div class="add-on" ng-show="pager.isBusy"> <i class="icon-spinner icon-spin"></i> </div> </div> </div> <div class="col-md-6 form-inline"> <small class="pull-right"> showing {{pager.displayBeginRecord()}} to {{pager.displayEndRecord()}} out of {{pager.totalRecords}} records .. <input type="text" ng-model="pager.numRecordsPerPage" class="form-control" ng-model-onblur ng-change="pager.initAndGetRecords()" style="width:54px"/> records per page</small> </div> </div> </div>----------------
Finally, the pager code:
function pager() { var that = this; that.isBusy = false; that.currentBeginRecord = 0; that.totalRecords = 0; that.numRecordsPerPage = 10; that.currentPage = 1; that.totalPages = 1; that.records = []; that.currentEndRecord = function () { return (that.currentBeginRecord + that.records.length - 1); }; that.canGoBack = function () { return (that.currentBeginRecord > 0 && !that.isBusy); }; var isNumeric = function (n) { return !isNaN(parseFloat(n)) && isFinite(n); }; that.canGoForward = function () { return (that.currentBeginRecord + that.records.length < that.totalRecords && !that.isBusy); }; that.cannotGoBack = function () { return !that.canGoBack(); } that.cannotGoForward = function () { return !that.canGoForward(); } that.displayBeginRecord = function () { return that.currentBeginRecord + 1; }; that.displayEndRecord = function () { return that.currentEndRecord() + 1; }; that.onRecordsFetched = function (data) { that.records = data.Records; that.totalRecords = data.TotalRecords; that.totalPages = Math.ceil(data.TotalRecords / that.numRecordsPerPage); that.currentPage = Math.ceil((that.currentBeginRecord + 1) / that.numRecordsPerPage); that.isBusy = false; }; that.goToPage = function () { var cp = that.currentPage; if (isNumeric(cp) && cp > 0 && cp <= that.totalPages) { that.currentBeginRecord = (cp - 1) * that.numRecordsPerPage; that.getRecords(); } } that.getRecords = function () { that.isBusy = true; if (typeof this.onGetRecords === "function") { this.onGetRecords(); } } that.initAndGetRecords = function () { that.currentBeginRecord = 0; that.getRecords(); } that.goToBeginning = function () { that.currentBeginRecord = 0; that.getRecords(); }; that.pageRefresh = function () { that.getRecords(); }; that.goForward = function () { that.currentBeginRecord = that.currentBeginRecord + that.records.length; that.getRecords(); }; that.goBack = function () { that.currentBeginRecord = that.currentBeginRecord - that.numRecordsPerPage; if (that.currentBeginRecord < 0) that.currentBeginRecord = 0; that.getRecords(); }; that.goToEnd = function () { var recsInLastPage = that.totalRecords % that.numRecordsPerPage; if (recsInLastPage < 1) recsInLastPage = that.numRecordsPerPage; that.currentBeginRecord = that.totalRecords - recsInLastPage; if (that.currentBeginRecord < 0) that.currentBeginRecord = 0; that.getRecords(); }; }