如何在AngularJS中进行分页?

我有一个在内存中大约1000项目的数据集,并试图为这个数据集创build一个寻呼机,但我不知道如何做到这一点。

我正在使用自定义筛选function来筛选结果,而且工作正常,但不知何故,我需要得到的页数。

任何线索?

Angular UI Bootstrap – 分页指令

查看UI Bootstrap的分页指令 。 我最终使用它,而不是在这里发布的,因为它有足够的function为我目前的使用,并有一个彻底的testing规范陪它。

视图

<!-- table here --> <pagination ng-model="currentPage" total-items="todos.length" max-size="maxSize" boundary-links="true"> </pagination> <!-- items/page select here if you like --> 

调节器

 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); }); }); 

我已经做了一个工作的强盗参考。


旧版本:

视图

 <!-- 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 --> 

调节器

 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); }); }); 

我已经做了一个工作的强盗参考。

我最近为Built with Angular网站实施了分页。 您chan签出来源: https : //github.com/angular/builtwith.angularjs.org

我会避免使用filter分离页面。 你应该把项目分解成控制器内的页面。

我不得不使用Angular进行分页,对于我觉得可以简化的东西来说,总是有些痛苦。 我已经使用了一些在这里和其他地方提出的想法来创build一个分页模块,使分页简单如下:

 <ul> <li dir-paginate="item in items | itemsPerPage: 10">{{ item }}</li> </ul> // then somewhere else on the page .... <dir-pagination-controls></dir-pagination-controls> 

而已。 它具有以下特点:

  • 您的控制器中不需要自定义代码来将收集items绑定到分页链接。
  • 你不必使用表或gridview – 你可以分页任何你可以重复!
  • 代表ng-repeat ,所以你可以使用任何可以在ng-repeat有效使用的expression式,包括过滤,sorting等。
  • 跨控制器工作 – pagination-controls指令不需要知道任何关于paginate指令被调用的上下文。

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

对于那些正在寻找“即插即用”解决scheme的人来说,我认为你会发现这个有用的。

这个代码在GitHub上可以find,包含了一系列相当不错的testing:

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

如果你有兴趣,我还写了一个短片,更深入地了解模块的devise: http : //www.michaelbromley.co.uk/blog/108/paginate-almost-anything-in-angularjs/

我只是做了一个JSFiddle显示分页+search+顺序在每列使用btford代码: http : //jsfiddle.net/SAWsA/11/

我更新了Scotty.NET的 plunkr http://plnkr.co/edit/FUeWwDu0XzO51lyLAEIA?p=preview,以便使用更新版本的angular,angular-ui和bootstrap。;

调节器

 var todos = angular.module('todos', ['ui.bootstrap']); todos.controller('TodoController', function($scope) { $scope.filteredTodos = []; $scope.itemsPerPage = 30; $scope.currentPage = 4; $scope.makeTodos = function() { $scope.todos = []; for (i=1;i<=1000;i++) { $scope.todos.push({ text:'todo '+i, done:false}); } }; $scope.figureOutTodosToDisplay = function() { var begin = (($scope.currentPage - 1) * $scope.itemsPerPage); var end = begin + $scope.itemsPerPage; $scope.filteredTodos = $scope.todos.slice(begin, end); }; $scope.makeTodos(); $scope.figureOutTodosToDisplay(); $scope.pageChanged = function() { $scope.figureOutTodosToDisplay(); }; }); 

引导UI组件

  <pagination boundary-links="true" max-size="3" items-per-page="itemsPerPage" total-items="todos.length" ng-model="currentPage" ng-change="pageChanged()"></pagination> 

这是一个纯粹的JavaScript解决scheme,我已经包装为一个Angular服务来实现分页逻辑,就像在谷歌search结果。

在CodePen上的工作演示http://codepen.io/cornflourblue/pen/KVeaQL/

在这个博客文章的细节和解释

 function PagerService() { // service definition var service = {}; service.GetPager = GetPager; return service; // service implementation function GetPager(totalItems, currentPage, pageSize) { // default to first page currentPage = currentPage || 1; // default page size is 10 pageSize = pageSize || 10; // calculate total pages var totalPages = Math.ceil(totalItems / pageSize); var startPage, endPage; if (totalPages <= 10) { // less than 10 total pages so show all startPage = 1; endPage = totalPages; } else { // more than 10 total pages so calculate start and end pages if (currentPage <= 6) { startPage = 1; endPage = 10; } else if (currentPage + 4 >= totalPages) { startPage = totalPages - 9; endPage = totalPages; } else { startPage = currentPage - 5; endPage = currentPage + 4; } } // calculate start and end item indexes var startIndex = (currentPage - 1) * pageSize; var endIndex = startIndex + pageSize; // create an array of pages to ng-repeat in the pager control var pages = _.range(startPage, endPage + 1); // return object with all pager properties required by the view return { totalItems: totalItems, currentPage: currentPage, pageSize: pageSize, totalPages: totalPages, startPage: startPage, endPage: endPage, startIndex: startIndex, endIndex: endIndex, pages: pages }; } } 

我在这里提取了相关的部分。 这是一个“无褶边”的表格传呼机,所以不包括sorting或筛选。 随时根据需要更改/添加:

  //your data source may be different. the following line is //just for demonstration purposes only var modelData = [{ text: 'Test1' }, { text: 'Test2' }, { text: 'Test3' }]; (function(util) { util.PAGE_SIZE = 10; util.range = function(start, end) { var rng = []; if (!end) { end = start; start = 0; } for (var i = start; i < end; i++) rng.push(i); return rng; }; util.Pager = function(data) { var self = this, _size = util.PAGE_SIZE;; self.current = 0; self.content = function(index) { var start = index * self.size, end = (index * self.size + self.size) > data.length ? data.length : (index * self.size + self.size); return data.slice(start, end); }; self.next = function() { if (!self.canPage('Next')) return; self.current++; }; self.prev = function() { if (!self.canPage('Prev')) return; self.current--; }; self.canPage = function(dir) { if (dir === 'Next') return self.current < self.count - 1; if (dir === 'Prev') return self.current > 0; return false; }; self.list = function() { var start, end; start = self.current < 5 ? 0 : self.current - 5; end = self.count - self.current < 5 ? self.count : self.current + 5; return Util.range(start, end); }; Object.defineProperty(self, 'size', { configurable: false, enumerable: false, get: function() { return _size; }, set: function(val) { _size = val || _size; } }); Object.defineProperty(self, 'count', { configurable: false, enumerable: false, get: function() { return Math.ceil(data.length / self.size); } }); }; })(window.Util = window.Util || {}); (function(ns) { ns.SampleController = function($scope, $window) { $scope.ModelData = modelData; //instantiate pager with array (ie our model) $scope.pages = new $window.Util.Pager($scope.ModelData); }; })(window.Controllers = window.Controllers || {}); 
 <script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"></script> <table ng-controller="Controllers.SampleController"> <thead> <tr> <th> Col1 </th> </tr> </thead> <tbody> <tr ng-repeat="item in pages.content(pages.current)" title="{{item.text}}"> <td ng-bind-template="{{item.text}}"></td> </tr> </tbody> <tfoot> <tr> <td colspan="4"> <a href="#" ng-click="pages.prev()">&laquo;</a> <a href="#" ng-repeat="n in pages.list()" ng-click="pages.current = n" style="margin: 0 2px;">{{n + 1}}</a> <a href="#" ng-click="pages.next()">&raquo;</a> </td> </tr> </tfoot> </table> 

jQuery Mobileangular度适配器有一个可以基于的分页filter。

这是一个演示小提琴使用它(添加超过5个项目,它变成分页): http : //jsfiddle.net/tigbro/Du2DY/

这里的来源: https : //github.com/tigbro/jquery-mobile-angular-adapter/blob/master/src/main/webapp/utils/paging.js

对于任何人发现像我这样的困难创build一个表的paginator我张贴这个。 所以,在你看来:

  <pagination total-items="total" items-per-page="itemPerPage" ng-model="currentPage" ng-change="pageChanged()"></pagination> <!-- To specify your choice of items Per Pages--> <div class="btn-group"> <label class="btn btn-primary" ng-model="radioModel" btn-radio="'Left'" data-ng-click="setItems(5)">5</label> <label class="btn btn-primary" ng-model="radioModel" btn-radio="'Middle'" data-ng-click="setItems(10)">10</label> <label class="btn btn-primary" ng-model="radioModel" btn-radio="'Right'" data-ng-click="setItems(15)">15</label> </div> //And don't forget in your table: <tr data-ng-repeat="p in profiles | offset: (currentPage-1)*itemPerPage | limitTo: itemPerPage" > 

在你的angularJs中:

  var module = angular.module('myapp',['ui.bootstrap','dialogs']); module.controller('myController',function($scope,$http){ $scope.total = $scope.mylist.length; $scope.currentPage = 1; $scope.itemPerPage = 2; $scope.start = 0; $scope.setItems = function(n){ $scope.itemPerPage = n; }; // In case you can replace ($scope.currentPage - 1) * $scope.itemPerPage in <tr> by "start" $scope.pageChanged = function() { $scope.start = ($scope.currentPage - 1) * $scope.itemPerPage; }; }); //and our filter module.filter('offset', function() { return function(input, start) { start = parseInt(start, 10); return input.slice(start); }; }); 

我使用这个第三方分页库,它运作良好。 它可以做本地/远程数据源,并且它是非常可configuration的。

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

 <dir-pagination-controls [max-size=""] [direction-links=""] [boundary-links=""] [on-page-change=""] [pagination-id=""] [template-url=""] [auto-hide=""]> </dir-pagination-controls> 

ng-repeat分页

  <div ng-app="myApp" ng-controller="MyCtrl"> <input ng-model="q" id="search" class="form-control" placeholder="Filter text"> <select ng-model="pageSize" id="pageSize" class="form-control"> <option value="5">5</option> <option value="10">10</option> <option value="15">15</option> <option value="20">20</option> </select> <ul> <li ng-repeat="item in data | filter:q | startFrom:currentPage*pageSize | limitTo:pageSize"> {{item}} </li> </ul> <button ng-disabled="currentPage == 0" ng-click="currentPage=currentPage-1"> Previous </button> {{currentPage+1}}/{{numberOfPages()}} <button ng-disabled="currentPage >= getData().length/pageSize - 1" ng- click="currentPage=currentPage+1"> Next </button> </div> <script> var app=angular.module('myApp', []); app.controller('MyCtrl', ['$scope', '$filter', function ($scope, $filter) { $scope.currentPage = 0; $scope.pageSize = 10; $scope.data = []; $scope.q = ''; $scope.getData = function () { return $filter('filter')($scope.data, $scope.q) } $scope.numberOfPages=function(){ return Math.ceil($scope.getData().length/$scope.pageSize); } for (var i=0; i<65; i++) { $scope.data.push("Item "+i); } }]); app.filter('startFrom', function() { return function(input, start) { start = +start; //parse to int return input.slice(start); } }); </script> 

以前的消息基本上build议如何自己build立一个分页。 如果你像我一样,并且喜欢完成的指令,我只是发现了一个很好的名字ngTable 。 它支持sorting,过滤和分页。

这是一个非常干净的解决scheme,只需要您的观点:

  <table ng-table="tableParams" class="table"> <tr ng-repeat="user in $data"> <td data-title="'Name'" sortable="'name'"> {{user.name}} </td> <td data-title="'Age'" sortable="'age'"> {{user.age}} </td> </tr> </table> 

在控制器中:

 $scope.tableParams = new ngTableParams({ page: 1, // show first page count: 10, // count per page sorting: { name: 'asc' // initial sorting } }, { total: data.length, // length of data getData: function($defer, params) { // use build-in angular filter var orderedData = params.sorting() ? $filter('orderBy')(data, params.orderBy()) : data; var start = (params.page() - 1) * params.count(); var end = params.page() * params.count(); $defer.resolve(orderedData.slice( start, end)); } }); 

链接到GitHub: https : //github.com/esvit/ng-table/

有我的例子。 在列表Controller中selectbutton。 configuration>>>

  $scope.pagination = {total: null, pages: [], config: {count: 10, page: 1, size: 7}}; 

逻辑分页:

 /* Pagination */ $scope.$watch('pagination.total', function (total) { if(!total || total <= $scope.pagination.config.count) return; _setPaginationPages(total); }); function _setPaginationPages(total) { var totalPages = Math.ceil(total / $scope.pagination.config.count); var pages = []; var start = $scope.pagination.config.page - Math.floor($scope.pagination.config.size/2); var finish = null; if((start + $scope.pagination.config.size - 1) > totalPages){ start = totalPages - $scope.pagination.config.size; } if(start <= 0) { start = 1; } finish = start + $scope.pagination.config.size - 1; if(finish > totalPages){ finish = totalPages; } for (var i = start; i <= finish; i++) { pages.push(i); } $scope.pagination.pages = pages; } $scope.$watch("pagination.config.page", function(page){ _setPaginationPages($scope.pagination.total); _getRespondents($scope.pagination.config); }); 

和我在bootstap上的看法

 <ul ng-class="{hidden: pagination.total == 0}" class="pagination"> <li ng-click="pagination.config.page = pagination.config.page - 1" ng-class="{disabled: pagination.config.page == 1}" ><a href="#">&laquo;</a></li> <li ng-repeat="p in pagination.pages" ng-click="pagination.config.page = p" ng-class="{active: p == pagination.config.page}"><a href="#">{{p}}</a></li> <li ng-click="pagination.config.page = pagination.config.page + 1" ng-class="{disabled: pagination.config.page == pagination.pages.length}"><a href="#">&raquo;</a></li> </ul > 

这是有用的

下面的解决scheme很简单

 <pagination total-items="totalItems" items-per-page= "itemsPerPage" ng-model="currentPage" class="pagination-sm"> </pagination> <tr ng-repeat="country in countries.slice((currentPage -1) * itemsPerPage, currentPage * itemsPerPage) "> 

这里是样品jsfiddle

我希望我可以发表评论,但我只需要在这里留下:

Scotty.NET的答案和user2176745的更新版本的重做都很好,但是他们都错过了我的AngularJS(v1.3.15)的版本:

我没有在$ scope.makeTodos中定义。

因此,使用此function进行更换可以修复更新的angular度版本。

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

概述使用分页

  - ng-repeat - uib-pagination 

查看

 <div class="row"> <div class="col-lg-12"> <table class="table"> <thead style="background-color: #eee"> <tr> <td>Dispature</td> <td>Service</td> <td>Host</td> <td>Value</td> </tr> </thead> <tbody> <tr ng-repeat="x in app.metricsList"> <td>{{x.dispature}}</td> <td>{{x.service}}</td> <td>{{x.host}}</td> <td>{{x.value}}</td> </tr> </tbody> </table> <div align="center"> <uib-pagination items-per-page="app.itemPerPage" num-pages="numPages" total-items="app.totalItems" boundary-link-numbers="true" ng-model="app.currentPage" rotate="false" max-size="app.maxSize" class="pagination-sm" boundary-links="true" ng-click="app.getPagableRecords()"></uib-pagination> <div style="float: right; margin: 15px"> <pre>Page: {{app.currentPage}} / {{numPages}}</pre> </div> </div> </div> </div> 

JS控制器

 app.controller('AllEntryCtrl',['$scope','$http','$timeout','$rootScope', function($scope,$http,$timeout,$rootScope){ var app = this; app.currentPage = 1; app.maxSize = 5; app.itemPerPage = 5; app.totalItems = 0; app.countRecords = function() { $http.get("countRecord") .success(function(data,status,headers,config){ app.totalItems = data; }) .error(function(data,status,header,config){ console.log(data); }); }; app.getPagableRecords = function() { var param = { page : app.currentPage, size : app.itemPerPage }; $http.get("allRecordPagination",{params : param}) .success(function(data,status,headers,config){ app.metricsList = data.content; }) .error(function(data,status,header,config){ console.log(data); }); }; app.countRecords(); app.getPagableRecords(); }]); 

angular寻呼

是一个很好的select

一个指令,以帮助分页大型数据集,同时要求最低限度的实际寻呼信息。 我们非常依赖服务器在这个分页scheme中“过滤”结果。 我们的核心思想是只保留项目的活动“页面”,而不是将整个项目列表保存在客户端的内存和分页中。

老问题,但因为我认为我的方法有点不同,不那么复杂,我会分享这个,希望除了我之外的其他人觉得它有用。

我发现对于分页来说,一个简单而小巧的解决scheme是将一个指令与一个使用相同范围variables的filter结合起来。

要实现这个,你需要在数组上添加filter,并像这样添加directiv

 <div class="row"> <table class="table table-hover"> <thead> <tr> <th>Name</th> <th>Price</th> <th>Quantity</th> </tr> </thead> <tbody> <tr ng-repeat="item in items | cust_pagination:p_Size:p_Step"> <td>{{item.Name}}</td> <td>{{item.Price}}</td> <td>{{item.Quantity}}</td> </tr> </tbody> </table> <div cust-pagination p-items="items" p-boundarylinks="true" p-size="p_Size" p-step="p_Step"></div> </div> 

p_Size和p_Step是范围variables,可以在范围内定制,否则p_Size的默认值是5,p_Step是1。

当一个步骤改变了分页时,p_Step被更新,并将触发cust_paginationfilter的新过滤。 cust_paginationfilter然后根据下面的p_Step值切片数组,并且只返回在分页部分中select的活动logging

 var startIndex = nStep * nPageSize; var endIndex = startIndex + nPageSize; var arr = items.slice(startIndex, endIndex); return arr; 

DEMO 查看此运动员的完整解决scheme

您可以使用Bootstrap UI指令轻松完成此操作。

这个答案是由@ Scotty.NET给出的答案的修改,我已经改变了代码,因为现在不推荐使用<pagination>指令。

以下代码生成分页:

 <ul uib-pagination boundary-links="true" total-items="totalItems" items-per-page="itemsPerPage" ng-model="currentPage" ng-change="pageChanged()" class="pagination" previous-text="&lsaquo;" next-text="&rsaquo;" first-text="&laquo;" last-text="&raquo;"></ul> 

要使其function正常,请在控制器中使用此function:

 $scope.filteredData = [] $scope.totalItems = $scope.data.length; $scope.currentPage = 1; $scope.itemsPerPage = 5; $scope.setPage = function (pageNo) { $scope.currentPage = pageNo; }; $scope.pageChanged = function() { var begin = (($scope.currentPage - 1) * $scope.itemsPerPage) , end = begin + $scope.itemsPerPage; $scope.filteredData = $scope.data.slice(begin, end); }; $scope.pageChanged(); 

有关分页的更多选项,请参阅此: Bootstrap UI分页指令

我想添加我的解决scheme,使用ngRepeat和filter,您使用它,而不使用$watch或切片数组。

你的过滤结果将分页!

 var app = angular.module('app', ['ui.bootstrap']); app.controller('myController', ['$scope', function($scope){ $scope.list= ['a', 'b', 'c', 'd', 'e']; $scope.pagination = { currentPage: 1, numPerPage: 5, totalItems: 0 }; $scope.searchFilter = function(item) { //Your filter results will be paginated! //The pagination will work even with other filters involved //The total number of items in the result of your filter is accounted for }; $scope.paginationFilter = function(item, index) { //Every time the filter is used it restarts the totalItems if(index === 0) $scope.pagination.totalItems = 0; //This holds the totalItems after the filters are applied $scope.pagination.totalItems++; if( index >= (($scope.pagination.currentPage - 1) * $scope.pagination.numPerPage) && index < ((($scope.pagination.currentPage - 1) * $scope.pagination.numPerPage) + $scope.pagination.numPerPage) ) return true; //return true if item index is on the currentPage return false; }; }]); 

在HTML中,请确保在分页filter之前将filter应用于ngRepeat

 <table data-ng-controller="myController"> <tr data-ng-repeat="item in list | filter: searchFilter | filter: paginationFilter track by $index"> <td> {{item}} </td> <tr> </table> <ul class="pagination-sm" uib-pagination data-boundary-links="true" data-total-items="pagination.totalItems" data-items-per-page="pagination.numPerPage" data-ng-model="pagination.currentPage" data-previous-text="&lsaquo;" data-next-text="&rsaquo;" data-first-text="&laquo;" data-last-text="&raquo;"> </ul>