如何显示经过过滤的ng-repeat数据的长度


438

我有一个包含许多对象(JSON格式)的数据数组。以下内容可以假定为该数组的内容:

var data = [
  {
    "name": "Jim",
    "age" : 25
  },
  {
    "name": "Jerry",
    "age": 27
  }
];

现在,我将这些详细信息显示为:

<div ng-repeat="person in data | filter: query">
</div

在此,查询被建模为一个输入字段,用户可以在其中限制显示的数据。

现在,我在另一个位置显示了当前正在显示的人数。 Showing {{data.length}} Persons

我想做的是,当用户搜索一个人并且根据查询过滤显示的数据时,这Showing...persons也改变了当前显示的人的价值。但这没有发生。它总是显示数据中的总人数,而不是过滤后的人数-如何获得过滤数据的计数?

Answers:


746

对于Angular 1.3以上版本(记入@Tom)

使用别名表达式(文档:Angular 1.3.0:ngRepeat,向下滚动到Arguments部分):

<div ng-repeat="person in data | filter:query as filtered">
</div>

对于1.3之前的Angular

将结果分配给新变量(例如filtered)并访问它:

<div ng-repeat="person in filtered = (data | filter: query)">
</div>

显示结果数:

Showing {{filtered.length}} Persons

提一个类似的例子。积分归Pawel Kozlowski所有


42
这是简单的答案,不会重复执行过滤器。
2014年

3
@本:是的。您可以使用在控制器内部访问它$scope.filtered.length
Wumms 2014年

2
那对我不起作用。记录undefined,可能是因为在记录它时,该变量尚未定义。那么,如何在定义变量并在视图中应用过滤器确保控制器中的代码运行?
2014年

6
@本:我想这已经不合时宜了。我会考虑创建一个自定义过滤器,例如jsfiddle,但是,您也可以在控制器中观看它:$scope.$watch('filtered', function() { console.log('filtered:', $scope.filtered); });
Wumms 2014年

3
如果我想添加limitTo:,则1.3+版本不起作用person in data | filter:query as filtered | limitTo:5。因此,我必须使用1.3之前的版本:person in filtered = (data | filter: query) | limitTo: 5
benjovanic

332

为了完整起见,除了前面的答案(在控制器内执行可见人员的计算)之外,您还可以在HTML模板中执行该计算,如下例所示。

假设您的人员列表处于data可变状态,并且使用query模型过滤人员,则以下代码将为您工作:

<p>Number of visible people: {{(data|filter:query).length}}</p>
<p>Total number of people: {{data.length}}</p>
  • {{data.length}} -打印总人数
  • {{(data|filter:query).length}} -打印已过滤的人数

请注意,如果您只想在一个页面中使用过滤的数据一次,则此解决方案效果很好。但是,如果您多次使用过滤后的数据(例如,为了显示项目并显示过滤后的列表的长度),我建议对AngularJS 1.3+使用别名表达式(如下所述),或者对@Wumms针对1.3之前的AngularJS版本使用解决方案。

Angular 1.3的新功能

AngularJS的创建者也注意到了这个问题,在1.3(测试版17)中,他们添加了“别名”表达式,该表达式将在应用过滤器后存储转发器的中间结果,例如

<div ng-repeat="person in data | filter:query as results">
    <!-- template ... -->
</div>

<p>Number of visible people: {{results.length}}</p>

别名表达式将防止多重滤波执行问题。

我希望这会有所帮助。


4
这是否意味着过滤器将执行两次?
Flash

9
是的,它执行了两次。
nathancahill 2014年

11
确保在决定使用此答案之前,先阅读@Wumms答案(您不会)...
epeleg 2014年

1
没关系,当您发表评论时,我看到答案不包含有关别名表达式的部分。
亚当·古德温

2
与当前的最佳答案不同,该答案支持多个过滤器表达式。即){{(data|filter:query|filter:query2).length}}
chakeda '16

45

如果有的话,最简单的方法

<div ng-repeat="person in data | filter: query"></div>

过滤数据长度

<div>{{ (data | filter: query).length }}</div>

这对于使用angular utils dir-paginate指令的任何人都是最有用的,因为不支持别名和preng-1.3替代。
pcnate

这会枚举两次数据吗?
杰普

36

ngRepeat在应用过滤器时会创建该数组的副本,因此您不能使用源数组仅引用已过滤的元素。

在您的情况下,最好使用以下$filter服务将过滤器应用于控制器内部:

function MainCtrl( $scope, filterFilter ) {
  // ...

  $scope.filteredData = myNormalData;

  $scope.$watch( 'myInputModel', function ( val ) {
    $scope.filteredData = filterFilter( myNormalData, val );
  });

  // ...
}

然后,您可以filteredData在视图中使用该属性。这是工作正常的柱塞:http ://plnkr.co/edit/7c1l24rPkuKPOS5o2qtx?p=preview


1
我了解的是,我使用{{filteredData.length}}而不是data.length。我还了解到myInputModel映射到输入查询的模型将过滤数据。val将是在输入中键入的文本(基本上是查询),但每次键入时都会更改。但是filterFilter这里是什么?我可能会补充说,我创建了自己的customFilter(可以在其中指定要考虑进行过滤的对象的键)。
user109187 2013年

那就对了。也可以使用,ng-repeat="person in filteredData"因为没有意义将其过滤两次。通过$filter服务,你可以只是“过滤器”,如后面添加它要求一个特定的过滤器:dateFilterjsonFilter等等。如果您正在使用自己的自定义过滤器,只需使用的那一个,而不是通用filterFilter
乔什·大卫·米勒

将多个过滤器应用于一个ng-repeat,假设您有2个带值的下拉列表和1个文本输入字段,该怎么办?
炼金术2013年

该过滤器只是一个函数,因此您只需将第一个过滤器的输出传递给第二个过滤器。
乔什·大卫·米勒

29

从AngularJS 1.3开始,您可以使用别名:

item in items | filter:x as results

在某处:

<span>Total {{results.length}} result(s).</span>

文档

您还可以提供一个可选的别名表达式,该别名表达式将在应用过滤器后存储转发器的中间结果。通常,当转发器上的过滤器处于活动状态但过滤的结果集为空时,此消息用于呈现特殊消息。

例如:item in items | filter:x as results将重复项的片段存储为结果,但仅在通过过滤器处理了这些项之后。


我无法应用$scope.$watch此别名结果。$broadcast有关别名results变量的任何提示?
DeBraid

25

还需要注意的是,可以通过对过滤器进行分组来存储多个级别的结果

all items: {{items.length}}
filtered items: {{filteredItems.length}}
limited and filtered items: {{limitedAndFilteredItems.length}}
<div ng-repeat="item in limitedAndFilteredItems = (filteredItems = (items | filter:search) | limitTo:25)">...</div>

这是一个演示小提琴


13

这是工作示例,请参见柱塞

  <body ng-controller="MainCtrl">
    <input ng-model="search" type="text">
    <br>
    Showing {{data.length}} Persons; <br>
    Filtered {{counted}}
    <ul>
      <li ng-repeat="person in data | filter:search">
        {{person.name}}
      </li>
    </ul>
  </body>

<script> 
var app = angular.module('angularjs-starter', [])

app.controller('MainCtrl', function($scope, $filter) {
  $scope.data = [
    {
      "name": "Jim", "age" : 21
    }, {
      "name": "Jerry", "age": 26
    }, {
      "name": "Alex",  "age" : 25
    }, {
      "name": "Max", "age": 22
    }
  ];

  $scope.counted = $scope.data.length; 
  $scope.$watch("search", function(query){
    $scope.counted = $filter("filter")($scope.data, query).length;
  });
});


4
这种方法的问题是您要运行两次过滤器:一次在ngRepeat中运行,一次在控制器中运行。
Josh David Miller

是的,您是对的,能否根据您的答案发布您的工作示例,我想了解更多过滤器?谢谢。
Maksym 2013年

2
当然。这是工作中的Plunker:plnkr.co/edit/7c1l24rPkuKPOS5o2qtx ? p= preview。我刚刚编辑了你的。
乔什·戴维·米勒

10

您可以通过2种方法来做到这一点。在模板Controller中。在模板中,您可以将过滤后的数组设置为另一个变量,然后根据需要使用它。这是操作方法:

<ul>
  <li data-ng-repeat="user in usersList = (users | gender:filterGender)" data-ng-bind="user.name"></li>
</ul>
 ....
<span>{{ usersList.length | number }}</span>

如果需要示例,请参阅AngularJs过滤计数示例/演示

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.