How to do paging in AngularJS?
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.
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.
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 anng-repeat
, including filtering, ordering etc. - Works across controllers - the
pagination-controls
directive does not need to know anything about the context in which thepaginate
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/