我们决定在我们的应用程序中使用服务器端分页。实现非常简单:
假设我们在服务器端有这样的搜索操作:
[HttpGet]
public ActionResult GetPeopleByName(String term, Int32 itemsPerPage = 10, Int32 page = 0) {
var matches = this.people.Where(i => i.Name.Contains(term));
return Json(
data: new {
people = matches.Skip(itemsPerPage * page).Take(itemsPerPage).OrderBy(i => i.Name),
total = matches.Count()
},
behavior: JsonRequestBehavior.AllowGet
);
}
在客户端上我们有subscriptionHolderController
:
app.controller('subscriptionHolderController', ['$scope', '$http', function($scope, $http) {
$scope.matches = [];
$scope.itemsPerPage = 5;
$scope.currentPage = 0;
$scope.searchTerm = '';
// $scope.prevPage = function() { ... };
// $scope.prevPageDisabled = function() { ... };
// $scope.nextPage = function() { ... };
// $scope.nextPageDisabled = function() { ... };
$scope.pageCount = function() {
return Math.ceil($scope.totalPages / $scope.itemsPerPage);
};
$scope.$watch('currentPage', function() { $scope.search(); });
$scope.search = function() {
if($scope.searchTerm === '') return;
// initiate a GET-request with params: { page: $scope.currentPage, term: $scope.searchTerm, itemsPerPage: $scope.itemsPerPage }
}
$scope.matchesFound = function () { return $scope.matches.length > 0; }
}]);
问题
结果我们有一个简单的search-box
。但是我们的应用程序需要一种具有一些附加功能的搜索类型,它不会使用搜索字词,其结果集应该按照上面显示的方式进行分页。
如何为不同类型的搜索重用分页逻辑?
答案 0 :(得分:4)
在服务器端,您可以返回一个通用类,该类将保存您的数据,即行总数。
public class PagedResult<T>
{
public PagedResult(IEnumerable<T> data, long total)
{
Data = data;
Total = total;
}
public PagedResult()
{
}
public IEnumerable<T> Data { get; set; }
public long Total { get; set; }
}
你也可以为任何函数抽象输入参数:
public class PageInfo
{
public int Page { get; set; }
public int PageSize { get; set; }
public int Skip
{
get
{
return PageSize*(Page - 1);
}
}
public PageInfo(int page, int pageSize)
{
Page = page;
PageSize = pageSize;
}
}
一个实际的例子可能是:
[HttpGet]
public ActionResult GetPeopleByName(String term, PageInfo pageinfo) {
var matches = this.people.Where(i => i.Name.Contains(term));
var pagedResult = new PagedResult<AnySearchType>{
data = matches.Skip(pageinfo.skip).Take(pageinfo.size).OrderBy(i => i.Name),
total = matches.Count()
};
return Json(
data: pagedResult,
behavior: JsonRequestBehavior.AllowGet
);
}
在客户端,您可以使用指令通过传递以下参数来抽象分页逻辑:
查看强>
<div class="box-content" scroll-pager="pagerConfig">
your data
<div>
<强>控制器:强>
您可以通过以下配置:
$scope.pagerConfig = {
pageSize: 10,
data: 'model.Data', // some text reference to your model
total: 'model.Total', // some text reference to your model
currentPage: 1,
searchParamName: 'Text',// some text reference to your model
resource: projectResource,// pass a resource object
success: function (data, page, total) {
}
};
答案 1 :(得分:1)
为分页创建单独的类。在这个类中,您可以定义分页方法,您可以将分页应用于任何类型,并使用不同的参数,您也可以自定义应用分页和页面大小的字段。
答案 2 :(得分:0)
这就是我最终的结果:
app.directive('pager', function() {
return {
restrict: 'EA',
scope: {
onChange: '&',
items: '=',
itemsPerPage: '@'
},
replace: true,
templateUrl: '/scripts/js/app/pager.html',
link: function(scope, el, attrs) {
scope.currentPage = 1;
scope.isFirstPage = function() {
return scope.currentPage === 1;
}
scope.decPage = function() {
if(scope.currentPage > 1) --scope.currentPage;
}
scope.isLastPage = function() {
return scope.currentPage >= scope.totalPages();
}
scope.totalPages = function() {
return Math.ceil(scope.items.total / scope.itemsPerPage);
}
scope.incPage = function() {
if(!scope.isLastPage()) ++scope.currentPage;
}
scope.$watch("currentPage", function(value) {
scope.onChange({page: value, itemsPerPage: scope.itemsPerPage});
});
}
};
});
<强>标记强>
<div id="content" ng-app="subscriptionsManager">
<div ng-controller="subscriptionHolderController">
<div class="row">
<div class="columns medium-6 large-6">
<div class="searchbar">
<div class="searchbar-inner">
<input ng-model="searchTerm" type="text" />
<button ng-click="search(1, 35)" class="tiny">search</button>
</div>
</div>
<div pager items-per-page="35" items="data" on-change="respondToTheChange(page, itemsPerPage)"></div>
</div>
<div class="columns medium-6 large-6">
<div class="button-group filter-sample">
<button ng-click="toggleState1()" ng-class="{true: 'selected', false: 'secondary'}[state1]" class="tiny">filter1</button>
<button ng-click="toggleState2()" ng-class="{true: 'selected', false: 'secondary'}[state2]" class="tiny">filter2</button>
<button ng-click="toggleState3()" ng-class="{true: 'selected', false: 'secondary'}[state3]" class="tiny">filter3</button>
<button ng-click="search2(1, 35)" class="tiny">search</button>
</div>
<div pager items-per-page="35" items="data2" on-change="respondToTheChange2(page, itemsPerPage)"></div>
</div>
</div>
</div>
</div>
<强>控制器强>
// search using a search term
$scope.data = { items: [], total: 0 };
$scope.searchTerm = '';
$scope.state1 = false;
$scope.state2 = false;
$scope.state3 = false;
$scope.toggleState1 = function() {
$scope.state1 = !$scope.state1;
}
$scope.toggleState2 = function() {
$scope.state2 = !$scope.state2;
}
$scope.toggleState3 = function() {
$scope.state3 = !$scope.state3;
}
$scope.search = function(page, itemsPerPage) {
if($scope.searchTerm === '') return;
if(!angular.isDefined(page) || page == null) page = 1;
if(!angular.isDefined(itemsPerPage) || itemsPerPage == null) itemsPerPage = 35;
$http({
url: '/subscriptions/GetSubscribersByNamePaged',
method: 'GET',
params: { term: $scope.searchTerm, page: page, itemsPerPage: itemsPerPage }
})
.success(function(data, status, headers, config) {
$scope.data = data;
}).error(function(data, status, headers, config) {
console.log('error: ' + data);
});
}
// search using anything else
$scope.search2 = function(page, itemsPerPage) {
if(!angular.isDefined(page) || page == null) page = 1;
if(!angular.isDefined(itemsPerPage) || itemsPerPage == null) itemsPerPage = 35;
$http({
url: '/subscriptions/GetSubscribersByFilters',
method: 'GET',
params: { state1: $scope.state1, state2: $scope.state2, state3: $scope.state3, page: page, itemsPerPage: itemsPerPage }
})
.success(function(data, status, headers, config) {
$scope.data2 = data;
}).error(function(data, status, headers, config) {
console.log('error: ' + data);
});
}
// bind searches!
$scope.respondToTheChange = function(page, itemsPerPage) {
$scope.search(page, itemsPerPage);
}
$scope.respondToTheChange2 = function(page, itemsPerPage) {
$scope.search2(page, itemsPerPage);
}