过滤后更新AngularJS中的分页
Posted
技术标签:
【中文标题】过滤后更新AngularJS中的分页【英文标题】:Update pagination in AngularJS after filtering 【发布时间】:2013-04-15 04:08:15 【问题描述】:我已经实现了分页。 现在我希望在过滤结果后更新分页。
形式:
<input type="text" data-ng-model="search.name" data-ng-change="filter()"/>
名单:
<li data-ng-repeat="data in filtered = (list | filter:search) | filter:search | startFrom:(currentPage-1)*entryLimit | limitTo:entryLimit">data.name</li>
分页:
<pagination data-boundary-links="true" data-num-pages="noOfPages" data-current-page="currentPage" max-size="maxSize"></pagination>
控制器:
$scope.filter = function()
window.setTimeout(function() //wait for 'filtered' to be changed
$scope.noOfPages = Math.ceil($scope.filtered.length/$scope.entryLimit);
$scope.setPage = function(pageNo)
$scope.currentPage = pageNo;
;
, 10);
;
我的问题是,在单击页码或在输入字段中输入下一个字符后,分页才会更新。所以更新晚了一步。
编辑:我将源添加到 jsFiddle:http://jsfiddle.net/eqCWL/2/
【问题讨论】:
【参考方案1】:使用$timeout
代替window.setTimeOut
。 $timeout
被正确包装以在 Angular 中始终如一地工作。
【讨论】:
【参考方案2】:使用角度$scope.$watch
$scope.$watch('search', function(term)
$scope.filter = function()
$scope.noOfPages = Math.ceil($scope.filtered.length/$scope.entryLimit);
);
来源; http://jsfiddle.net/eqCWL/2/
演示; http://jsfiddle.net/eqCWL/192/
【讨论】:
【参考方案3】:你可以简单地使用这个指令来代替:
https://github.com/michaelbromley/angularUtils/tree/master/src/directives/pagination
它通过过滤器提供分页,同时保持代码整洁。
感谢 michaelbromley 的出色代码。
【讨论】:
【参考方案4】:@abject_error 使用$timeout
的答案确实有效。我根据他的建议编辑了你的小提琴并制作了这个jsFiddle
警告
我认为这个解决方案以竞争条件的形式表明了一个更大的问题!
jsFiddle using filterFilter and $watch
而那个小提琴就是真正的解决方法。
这里是解释
您的竞争条件介于处理search
的更改和$scope.filtered
的可用性之间。
我认为为了解决这种竞争状况而要消除的罪魁祸首是:
ng-model="search" ng-change="filter()"
和
ng-repeat="data in filtered = (list | filter:search)......."
使用ng-change
触发“filter()”来计算noOfPages
,但也取决于搜索的变化以创建filtered
。这样做可以确保过滤后的列表可能无法及时准备好计算页数,这就是为什么将“filter()”延迟 10 毫秒并超时会给你一种工作程序的错觉。
您需要一种“观察”search
更改的方法,然后在您可以访问创建$scope.filtered
和计算$scope.noOfPages
的位置过滤列表。全部按顺序进行,没有比赛。
Angular 就是这样!可以在控制器中使用filter
过滤器作为名称非常糟糕的函数:filterFilter
。在Filters Guide - Using filters in controllers and services 中查看此内容
将其注入控制器。
function pageCtrl($scope, filterFilter)
// ...
在$watch
函数中使用它,记录在scopes docs中
$scope.$watch('search', function(term)
// Create filtered
$scope.filtered = filterFilter($scope.list, term);
// Then calculate noOfPages
$scope.noOfPages = Math.ceil($scope.filtered.length/$scope.entryLimit);
)
更改模板以反映我们的新方式。 DOM 过滤器中不再有,或 ng-change
<input type="text" ng-model="search" placeholder="Search"/>
和
<li ng-repeat="data in filtered | startFrom:(currentPage-1)*entryLimit | limitTo:entryLimit">
data.name
</li>
【讨论】:
这看起来像一个更好的解决方案,但如果我将 ng-model="search" 更改为 ng-model"search.name" 如下 它似乎坏了。这是什么原因造成的。我问这个是因为我希望能够过滤多个列 将监视表达式也更改为search.name
。您可能需要考虑 $watchCollection 是否适合您的情况。允许您查看对象的属性。
我已经弄清楚了 $watch 函数的第三个参数,但我认为 $watchCollection 更好。谢谢你。
我有自己的分页指令,因为我必须跨多个页面实现分页和搜索。在这种情况下,我如何将搜索逻辑添加到我的指令中,因为 ng-repeat 指的是控制器。如果我必须将此逻辑添加到控制器,那么我必须复制粘贴我所有页面的代码。有什么建议吗?
我在同一条船上......我喜欢这个解决方案,但我不确定如何在我的整个应用程序中实现它而不复制/粘贴每个控制器中的代码以上是关于过滤后更新AngularJS中的分页的主要内容,如果未能解决你的问题,请参考以下文章