使用 Angular.js 对过滤后的数据进行分页,并在视图/控制器中不重复代码地显示总项目数。
使用 Angular.js 对过滤后的数据进行分页,并在视图/控制器中不重复代码地显示总项目数。
假设我在视图中实现了一个过滤器,类似这样:
-
- {{ statement.Name }}
这将对任何包含statementFilter
的属性进行不区分大小写的部分匹配。
我需要在我的控制器中实现此过滤器,而不是在视图中。我知道你可以在Angular中创建自定义过滤器,但我希望我的过滤器能够对内置于视图中的任何复杂对象进行通用的不区分大小写的部分匹配。如果我创建一个自定义过滤器,我必须使用JavaScript进行实际过滤,这将需要另一个库AFAIK。
我怎样才能在代码中利用Angular的“视图”过滤器提供的通用不区分大小写的部分匹配?
谢谢。
更新
这是我想做的Plunker的链接:http://plnkr.co/edit/pX1D5GrUbjVzQo2RMbUz?p=preview。
这是另一种使用多个过滤器和分页实现相同结果的方法。除了这个版本不依赖于angular-ui来进行分页控制之外,实际上并没有什么优势。
app.js
var app = angular.module('statementApp', ['ui.bootstrap']); app.controller('statementController', function($scope, $interpolate) { $scope.currentPage = 0; $scope.pageSize = 10; $scope.data = [ {name:"John Smith", price:"1.20"}, {name:"John Smith", price:"1.20"}, {name:"Sam Smith", price:"1.20"}, {name:"Sam Smith", price:"1.20"}, {name:"Sam Smith", price:"1.20"}, {name:"Sam Smith", price:"1.20"}, {name:"Sarah Smith", price:"1.20"}, {name:"Sarah Smith", price:"1.20"}, {name:"Sarah Smith", price:"1.20"}, {name:"Sarah Smith", price:"1.20"}, {name:"Sarah Smith", price:"1.20"}, {name:"Sarah Smith", price:"1.20"} ]; var init = function() { $scope.initPaging(); } $scope.searchFilter = function(item) { if(!$scope.searchVal) return true; var qsRegex = new RegExp($scope.searchVal, 'gi'); return qsRegex ? item.name.match(qsRegex) : true; } $scope.initPaging = function() { $scope.currentPage = 0; $scope.numberOfPages=function(){ if($scope.filteredItems.length > $scope.pageSize) { return Math.ceil($scope.filteredItems.length / $scope.pageSize); } return 1; } } $scope.$watch(function () { $scope.filteredItems = $scope.$eval("data | filter:searchFilter | orderBy: 'price'"); }); init(); });
index.html
Total records: {{ filteredItems.length }}
Name | Price |
---|---|
{{item.name}} | {{item.price | currency:"£":0}} |
Plunker链接http://plnkr.co/edit/OWotCiVYBed77F50wdMf?p=preview
解决方案: http://plnkr.co/edit/AcAP437OJGMgMuGCtxT3?p=preview
基本上,问题是控制器在执行视图中已经实现的功能...大多数其他情况下都比这更困难,因为你正在尝试对过滤和显示长度的相同数据进行分页...所以这意味着必须按照以下顺序操纵数据:
- 基于搜索项过滤数据
- 获取过滤项的长度
- 分页过滤项并显示
我知道必须做的第一件事是重新构建ng-repeat
进行过滤。目标是使用内置的angular过滤器。
原始代码如下。 这是在控制器中使用自定义代码进行的过滤和分页。
data-ng-repeat="statement in pagedStatementData()"
步骤1:使用Angular过滤器
你在问题中发布的过滤器是处理此任务的简单方法,而不需要编写自定义过滤器代码...这是我的第一步。 很容易。
data-ng-repeat="statement in statements | filter:statementFilter"
步骤2:回到分页
此时,列表已正确过滤,但显示所有经过过滤的项目,而没有将它们分页。分页按钮按预期工作,总记录相应更新。 因此,现在的下一步是将该分页插入到该过滤列表中。
在脚本中,我将begin和end添加到作用域中。 这些变量以前是在pagedStatementData()
中创建的。 然后使用这些值,我可以将过滤后的数组切成固定大小,从而获得分页。
请注意:此时步骤5中最终删除了$ scope.begin $ scope.end代码,因为它只在初始渲染时计算,并且之后没有更新。这是我在第5步之前没有注意到的错误。
$scope.begin = ($scope.currentPage-1)*$scope.numPerPage; $scope.end = ($scope.begin + $scope.numPerPage); data-ng-repeat="statement in (statements | filter:statementFilter).slice(begin, end)"
步骤3:删除不需要的/不需要的控制器代码
此时,一切都有效...但是目标是删除自定义过滤代码... 因此,我删除了$scope.filteredStatementData
方法以及调用它的$scope.totalFilteredStatementItems
方法。 $scope.pagedStatementData
也可以删除。这是在步骤1中修改的ng-repeat
中调用的。
已删除:
- $scope.filteredStatementData //自定义过滤器代码...已删除
- $scope.totalFilteredStatementItems //调用filteredStatementData...已删除
- $scope.pagedStatementData //原来的ng-repeat调用了这个...已删除
步骤4:修复总项#和分页按钮。 两者都依赖于相同的.length
此时...视图已中断,因为它仍在对我们刚刚删除的一些方法(totalFilteredStatementItems)进行一些调用。现在的目标是用视图中拥有的替换那个功能。 totalFilteredStatementItems过去运行了自定义过滤逻辑,然后获取数据的长度,而不分页。
我们已经有了被过滤的项,所以只需在它们被分页之前将它们保存到作用域中(以便它们可以在其他地方被访问)。实际上,我们可以将过滤后的数组保存在ng-repeat中。只要语法保持为item in items
,但是items
可以赋给作用域变量,如item in (items = (/*过滤*/)).slice(x,y)
data-ng-repeat="statement in (filteredItems = (statements | filter:statementFilter)).slice(being, end)" Total records: {{ filteredItems.length }}
好的。ng-repeat开始变得复杂,但它仍然起作用。其中括号是真正的魔法。这段代码按照所需的顺序执行。
// filtered data based on search item $scope.filteredItems = $scope.statements.filter(/*statementFilter magic*/); // paginate the filtered items var _temp = filteredItems.slice($scope.begin, $scope.end), _i, statement; // display page of filtered items for (var _i in _temp) { statement = _temp[_i]; // Render each row w/ statement }
此外,我确定有一些Angular $scope的魔法来更新filteredItems.length,因为它在列表被过滤之前用于“总记录:”div中……感谢Angular!或者它优先考虑ng-repeat并首先执行该块。我不知道。它有效。
步骤5:分页已经损坏。获取分页组件更新依赖于列表的开头和结尾变量。
在控制器中删除了$scope.begin和$scope.end代码。
在组件被创建时,将它们创建在ng-init
内部,然后在data-ng-change
事件上重新计算这些值。