过滤后更新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中的分页的主要内容,如果未能解决你的问题,请参考以下文章

Angular 5中的分页索引号

ASP.NET 中的分页;过滤后页数不变

DRF的分页组件,过滤组件

如何在 Angular 8 中保存表格的分页、排序、搜索状态?我正在使用 angular2-datatable

AngularJS 1.6 分页不显示

使用 Bootstrap Angular 6 数据表的分页样式页脚