How to do paging in AngularJS?

I have a dataset of about 1000 items in-memory and am attempting to create a pager for this dataset, but I'm not sure on how to do this.

I'm using a custom filter function to filter the results, and that works fine, but somehow I need to get the number of pages out.

Any clues?


Solution 1:

Angular UI Bootstrap - Pagination Directive

Check out UI Bootstrap's pagination directive. I ended up using it rather than what is posted here as it has enough features for my current use and has a thorough test spec to accompany it.

View

<!-- table here -->

<pagination 
  ng-model="currentPage"
  total-items="todos.length"
  max-size="maxSize"  
  boundary-links="true">
</pagination>

<!-- items/page select here if you like -->

Controller

todos.controller("TodoController", function($scope) {
   $scope.filteredTodos = []
  ,$scope.currentPage = 1
  ,$scope.numPerPage = 10
  ,$scope.maxSize = 5;

  $scope.makeTodos = function() {
    $scope.todos = [];
    for (i=1;i<=1000;i++) {
      $scope.todos.push({ text:"todo "+i, done:false});
    }
  };
  $scope.makeTodos(); 

  $scope.$watch("currentPage + numPerPage", function() {
    var begin = (($scope.currentPage - 1) * $scope.numPerPage)
    , end = begin + $scope.numPerPage;

    $scope.filteredTodos = $scope.todos.slice(begin, end);
  });
});

I have made a working plunker for reference.


Legacy Version:

View

<!-- table here -->

<div data-pagination="" data-num-pages="numPages()" 
  data-current-page="currentPage" data-max-size="maxSize"  
  data-boundary-links="true"></div>

<!-- items/page select here if you like -->

Controller

todos.controller("TodoController", function($scope) {
   $scope.filteredTodos = []
  ,$scope.currentPage = 1
  ,$scope.numPerPage = 10
  ,$scope.maxSize = 5;

  $scope.makeTodos = function() {
    $scope.todos = [];
    for (i=1;i<=1000;i++) {
      $scope.todos.push({ text:"todo "+i, done:false});
    }
  };
  $scope.makeTodos(); 

  $scope.numPages = function () {
    return Math.ceil($scope.todos.length / $scope.numPerPage);
  };

  $scope.$watch("currentPage + numPerPage", function() {
    var begin = (($scope.currentPage - 1) * $scope.numPerPage)
    , end = begin + $scope.numPerPage;

    $scope.filteredTodos = $scope.todos.slice(begin, end);
  });
});

I have made a working plunker for reference.

Solution 2:

I recently implemented paging for the Built with Angular site. You chan checkout the source: https://github.com/angular/builtwith.angularjs.org

I'd avoid using a filter to separate the pages. You should break up the items into pages within the controller.

Solution 3:

I've had to implement pagination quite a few times with Angular, and it was always a bit of a pain for something that I felt could be simplified. I've used some of the ideas presented here and elsewhere to make a pagination module that makes pagination as simple as:

<ul>
    <li dir-paginate="item in items | itemsPerPage: 10">{{ item }}</li>
</ul>

// then somewhere else on the page ....

<dir-pagination-controls></dir-pagination-controls>

That's it. It has the following features:

  • No custom code needed in your controller to tie the collection items to the pagination links.
  • You aren't bound to using a table or gridview - you can paginate anything you can ng-repeat!
  • Delegates to ng-repeat, so you can use any expression that could be validly used in an ng-repeat, including filtering, ordering etc.
  • Works across controllers - the pagination-controls directive does not need to know anything about the context in which the paginate directive is called.

Demo : http://plnkr.co/edit/Wtkv71LIqUR4OhzhgpqL?p=preview

For those who are looking for a "plug and play" solution, I think you'll find this useful.

Code

The code is available here on GitHub and includes a pretty good set of tests:

https://github.com/michaelbromley/angularUtils/tree/master/src/directives/pagination

If you are interested I also wrote a short piece with a little more insight into the design of the module: http://www.michaelbromley.co.uk/blog/108/paginate-almost-anything-in-angularjs/

Solution 4:

I just made a JSFiddle that show pagination + search + order by on each column using btford code: http://jsfiddle.net/SAWsA/11/