angularUtils icon indicating copy to clipboard operation
angularUtils copied to clipboard

Pagination: pageChanged handler should accept `newPageSize` when working with Asynchronous Data

Open benoror opened this issue 10 years ago • 3 comments

When working with Asynchronous Data, a change in pageSize should re-trigger an async call as well (and possibly do some recalculation):

$scope.pageChanged = function(newPage, newPageSize) {
    getResultsPage(newPage, newPageSize);
};
<dir-pagination-controls on-page-change="pageChanged(newPageNumber, newPageSize)"></dir-pagination-controls>
  • Implementation example: How UI Grid handles pagination: http://ui-grid.info/docs/#/api/ui.grid.pagination.api:PublicAPI#events_paginationchanged
  • Dependant on: https://github.com/michaelbromley/angularUtils/issues/211

benoror avatar Aug 13 '15 17:08 benoror

Looking at uigrid's code I found a clue for the way the watcher is written:

https://github.com/angular-ui/ui-grid/blob/7420b4b54eba5798053b99d1c6c0dcc67c530080/src/features/pagination/js/pagination.js#L377

benoror avatar Aug 13 '15 18:08 benoror

Ok this is how I implemented this on application level, aklthoug it would be nice to be incorporated into the directive:

View:

<div class="panel-footer clearfix">
  <div class="pull-left">
    <select
      ng-model="vm.options.paginationPageSize"
      ng-options="o as o for o in vm.options.paginationPageSizes">
    </select>
    records per page
  </div>
  <dir-pagination-controls
    boundary-links="true"
    template-url="directives/shared/dirPagination.tpl.html">
  </dir-pagination-controls>
</div>

Controller:

  var vm = this;

  // Default options
  vm.options = {};
  vm.options.paginationPageSizes = [4, 8, 16, 32, 64, 128];
  vm.options.totalItems = 100;
  vm.options.paginationPageSize = 10;
  vm.options.currentPage = 1;

  // Instead of using on-page-change attribute, implement this watcher:
  $scope.$watch('vm.options.currentPage + vm.options.paginationPageSize', (newValues, oldValues) => {
    if (newValues === oldValues) {
      return;
    }
    vm.makeAjaxCall(vm.options.currentPage, vm.options.paginationPageSize)
  });

benoror avatar Aug 13 '15 18:08 benoror

Updated to avoid infinite loops in some scenarios:

  var vm = this;

  // Default options
  vm.options = {};
  vm.options.paginationPageSizes = [4, 8, 16, 32, 64, 128];
  vm.options.totalItems = 100;
  vm.options.paginationPageSize = 10;
  vm.options.currentPage = 1;

  vm.getTotalPages = function() {
    if (!vm.catalog.totalItems) { // (!vm.options.enablePagination) {
      return null;
    }
    return (vm.options.totalItems === 0) ? 1 : Math.ceil(vm.options.totalItems / vm.options.paginationPageSize);
  };

  // Instead of using on-page-change attribute, implement this watcher:
  $scope.$watch('vm.options.currentPage + vm.options.paginationPageSize', (newValues, oldValues) => {
    if (newValues === oldValues || oldValues === undefined) {
      return;
    }
    if (!angular.isNumber(vm.options.currentPage) || vm.options.currentPage < 1) {
      vm.options.currentPage = 1;
      return;
    }
    if (vm.options.totalItems > 0 && vm.options.currentPage > vm.getTotalPages()) {
      vm.options.currentPage = vm.getTotalPages();
      return;
    }

    vm.paginationChangeHandler({
      newPage: vm.options.currentPage,
      newPageSize: vm.options.paginationPageSize
    });
  });

Actually full credit goes to @brianchance who implemented this feature in ui-grid back in Nov 2014.

benoror avatar Aug 13 '15 22:08 benoror