继昨天写了knockoutjs+ jquery pagination+asp.net web Api 实现无刷新列表页 ,正好最近刚学习angularjs ,故琢磨着写一个angularjs版本的分页控件。
思路是自定义一个directive , 然后用isolated scope与父级controller $scope同步交互页数和当前页信息, 利用module的contant方法定义默认选项,从directive link 函数获取用户自定义选项设置。和以前写jquery插件的思路类似, 内部定义一个默认的defaults选项,利用jQuery.extend({},defaults,userCustomOption)合并用户自定义设置 ,然后动态构造html结构,只不过directive可以使用模板,模板中可以继续使用其他directive,所以构造html的工作可以分配给模板来做,劳累了半天总算可以跑起来了,劳动成果如下 angular.pagination.js
; (function(angular) { var myModule = angular.module("myModule", []); myModule.constant('pagexConfig', { visiblePageCount: 10, firstText: 'First', lastText: 'Last', prevText: 'Previous', nextText: 'Next' }).directive("pager", ['pagexConfig', function(pagexConfig) { return { link: function(scope, element, attrs) { var visiblePageCount = angular.isDefined(attrs.visiblePageCount) ? attrs.visiblePageCount : pagexConfig.visiblePageCount; scope.firstText = angular.isDefined(attrs.firstText) ? attrs.firstText : pagexConfig.firstText; scope.lastText = angular.isDefined(attrs.lastText) ? attrs.lastText : pagexConfig.lastText; scope.prevText = angular.isDefined(attrs.prevText) ? attrs.prevText : pagexConfig.prevText; scope.nextText = angular.isDefined(attrs.nextText) ? attrs.nextText : pagexConfig.nextText; scope.currentPage = 1; scope.pageChange = function(page) { if (page >= 1 && page <= scope.pageCount) { scope.currentPage = page; } else { scope.currentPage = 1; } } function build() { var low, high, v; scope.pagenums = []; if (scope.pageCount == 0) { return; } if (scope.currentPage > scope.pageCount) { scope.currentPage = 1; } if (scope.pageCount <= visiblePageCount) { low = 1; high = scope.pageCount; } else { v = Math.ceil(visiblePageCount / 2); low = Math.max(scope.currentPage - v, 1); high = Math.min(low + visiblePageCount - 1, scope.pageCount); if (scope.pageCount - high < v) { low = high - visiblePageCount + 1; } } for (; low <= high; low++) { scope.pagenums.push(low); } scope.onPageChange(); } scope.$watch('currentPage+pageCount', function() { build(); }); }, replace: true, restrict: "E", scope: { pageCount: '=', currentPage: '=', onPageChange: '&' }, template: '<ul class="pagination"><li ng-click="pageChange(1)">{{firstText}}</li>' + '<li ng-click="pageChange(currentPage-1>0?currentPage-1:1)">{{prevText}}</li>' + '<li ng-repeat="pagenum in pagenums" ng-click="pageChange(pagenum)" ng-class="{active:currentPage===pagenum}">{{pagenum}}</li>' + '<li ng-click="pageChange(currentPage+1<=pageCount?currentPage+1:pageCount)">{{nextText}}</li>' + '<li ng-click="pageChange(pageCount)">{{lastText}}</li></ul>' } }]); })(angular)
简单起见, 只定义了几个简单的自定义属性, first | last | prev | next (Text) 顾名思义就是首页,尾页,上一页,下一页, visiblePageCount是用户可见的页码块。
server 端代码继续用昨天knockoutjs 的 ,获取页数的稍作改变
using System.Collections.Generic; using System.Linq; using System.Web.Http; namespace WebApp.Api { public class Product { public int Id { get; set; } public string Name { get; set; } public string Category { get; set; } public decimal Price { get; set; } } public class TestController : ApiController { Product[] products = new Product[] { new Product { Id = 1, Name = "Tomato Soup", Category = "Groceries", Price = 1 }, new Product { Id = 2, Name = "Yo-yo", Category = "Toys", Price = 3.75M }, new Product { Id = 3, Name = "Hammer", Category = "Hardware", Price = 16.99M }, new Product { Id = 4, Name = "Tomato Soup", Category = "Groceries", Price = 1 }, new Product { Id = 5, Name = "Yo-yo", Category = "Toys", Price = 3.75M }, new Product { Id = 6, Name = "Hammer", Category = "Hardware", Price = 16.99M } , new Product { Id = 7, Name = "Tomato Soup", Category = "Groceries", Price = 1 }, new Product { Id = 8, Name = "Yo-yo", Category = "Toys", Price = 3.75M }, new Product { Id = 9, Name = "Hammer", Category = "Hardware", Price = 16.99M }, new Product { Id = 10, Name = "Tomato Soup", Category = "Groceries", Price = 1 }, new Product { Id = 11, Name = "Yo-yo", Category = "Toys", Price = 3.75M }, new Product { Id = 12, Name = "Hammer", Category = "Hardware", Price = 16.99M }, new Product { Id = 13, Name = "Tomato Soup", Category = "Groceries", Price = 1 }, new Product { Id = 14, Name = "Yo-yo", Category = "Toys", Price = 3.75M }, new Product { Id = 15, Name = "Hammer", Category = "Hardware", Price = 16.99M } , new Product { Id = 16, Name = "Tomato Soup", Category = "Groceries", Price = 1 }, new Product { Id = 17, Name = "Yo-yo", Category = "Toys", Price = 3.75M }, new Product { Id = 18, Name = "Hammer", Category = "Hardware", Price = 16.99M } }; [Route("api/getpagecount")] [HttpGet] public int GetCount() { return products.Length % 10 == 0 ? products.Length / 10 : products.Length / 10 + 1; } [Route("api/getdata")] [HttpGet] public IEnumerable<Product> GetProduct(int pageIndex, int pageSize) { return products.Skip(pageIndex * pageSize).Take(pageSize); } } }
view层页码代码
<!DOCTYPE html> <html> <head> <meta charset="utf-8" /> <meta name="viewport" content="width=device-width" /> <title>index</title> <link href="css/style.css" rel="stylesheet" /> </head> <body ng-app="app"> <div ng-controller="myCtrl"> <pager page-count="pageCount" current-page="currentPage" on-page-change="onPageChange()" first-text="首页" last-text="最后一页"></pager> </div> <script src="js/angular-1.2.21.min.js"></script> <script src="js/angular.pagination.js"></script> <script src="js/app.js"></script> </body> </html>
业务逻辑代码
var app = angular.module( 'app', ['myModule'] ); app.controller( 'myCtrl', function ( $scope, $http ) { $scope.onPageChange = function () { $http.get( '/api/getdata?pageIndex=' + ( $scope.currentPage - 1 ) + '&pageSize=10' ).success( function ( data ) { $scope.items = data; } ); } $http.get( '/api/getpagecount' ).success( function ( data ) { $scope.pageCount = data; } ); $http.get( '/api/getdata?pageIndex=0&pageSize=10' ).success( function ( data ) { $scope.items = data; } ); } );
运行效果图
纯html版本的已经 发布到github , 无须server端支持 https://github.com/leonwgc/angularjs-pagination