【问题标题】:How to display length of filtered ng-repeat data如何显示过滤后的 ng-repeat 数据的长度
【发布时间】:2013-02-25 07:37:39
【问题描述】:

我有一个包含许多对象(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 也会改变当前显示的人的值。但它没有发生。它始终显示数据中的总人数而不是过滤后的人数 - 我如何获得过滤数据的计数?

【问题讨论】:

    标签: javascript angularjs


    【解决方案1】:

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

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

    过滤后的数据长度

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

    【讨论】:

    • 这对于使用 angular utils dir-paginate 指令的任何人最有用,因为不支持别名和 pre ng-1.3 替代方案。
    • 这会枚举数据两次吗?
    【解决方案2】:

    您可以通过 2 种方式 做到这一点。在 template 和 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 filtered count examples/demos

    【讨论】:

      【解决方案3】:

      对于 Angular 1.3+(感谢 @Tom)

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

      <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
      

      拨弄similar example。致谢Pawel Kozlowski

      【讨论】:

      • 这是不重复执行过滤器的简单答案。
      • @Ben:是的。您可以使用$scope.filtered.length 在控制器内部访问它。
      • 这对我不起作用。记录undefined,可能是因为在记录它时,该变量尚未定义。那么如何确保控制器中的代码在 定义变量并在视图中应用过滤器之后运行?
      • @Ben:我想这已经跑题了。我会考虑创建一个自定义过滤器,例如jsfiddle,不过,您也可以在控制器内部观看:$scope.$watch('filtered', function() { console.log('filtered:', $scope.filtered); });
      • 如果我想添加limitTo,1.3+版本不起作用:person in data | filter:query as filtered | limitTo:5。所以我不得不使用 1.3 之前的版本:person in filtered = (data | filter: query) | limitTo: 5
      【解决方案4】:

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

      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>
      

      这是demo fiddle

      【讨论】:

        【解决方案5】:

        为了完整起见,除了之前的答案(在控制器内执行可见人物的计算)之外,您还可以在 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+ 或 @Wummsalias expression(如下所述) /em> 用于 AngularJS 1.3 之前的版本。

        Angular 1.3 中的新功能

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

        <div ng-repeat="person in data | filter:query as results">
            <!-- template ... -->
        </div>
        
        <p>Number of visible people: {{results.length}}</p>
        

        别名表达式将防止多个过滤器执行问题。

        我希望这会有所帮助。

        【讨论】:

        • 这是否意味着过滤器被执行了两次?
        • 是的,执行了两次。
        • 在你决定使用这个之前,请确保你阅读了@Wumms 的答案(你不会)......
        • 没关系,当您发表评论时,我看到答案没有包含有关别名表达式的部分。
        • 这个答案支持多个过滤器表达式,这与当前的最佳答案不同。即){{(data|filter:query|filter:query2).length}}
        【解决方案6】:

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

        item in items | filter:x as results
        

        在某处:

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

        来自docs:

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

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

        【讨论】:

        • 我无法将$scope.$watch 应用于此别名结果。 $broadcasting 别名 results 变量的任何提示?
        【解决方案7】:

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

        在您的情况下,使用$filter 服务在控制器内部应用过滤器可能会更好:

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

        然后您在视图中使用filteredData 属性。这是一个工作 Plunker:http://plnkr.co/edit/7c1l24rPkuKPOS5o2qtx?p=preview

        【讨论】:

        • 我的理解是我使用{{filteredData.length}}而不是data.length。我还了解到myInputModel 是映射到过滤数据的输入查询的模型。 val 将是在输入中输入的文本(基本上是查询),但每次我输入时,它都会改变。但是这里的filterFilter 是什么?我可能会补充一点,我创建了自己的 customFilter(我可以在其中指定要考虑过滤的对象的哪个键)。
        • 没错。也只需使用ng-repeat="person in filteredData",因为过滤两次是没有意义的。使用$filter 服务,您可以通过添加“过滤器”后缀来请求特定过滤器,例如:dateFilter、jsonFilter 等。如果您使用自己的自定义过滤器,只需使用该过滤器即可通用的filterFilter。
        • 对一个 ng-repeat 应用多个过滤器怎么样,假设您有 2 个带有值的下拉菜单和一个文本输入字段?
        • 过滤器只是一个函数,所以你只需将第一个过滤器的输出传递给第二个过滤器。
        【解决方案8】:

        这是工作示例See on Plunker

          <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;
          });
        });
        

        【讨论】:

        • 这种方法的问题是您运行过滤器两次:一次在 ngRepeat 中,一次在控制器中。
        • 是的,你是对的,你能根据你的回答发布你的工作示例吗,我想学习更多过滤器?谢谢。
        • 当然。这是工作中的 Plunker:plnkr.co/edit/7c1l24rPkuKPOS5o2qtx?p=preview。我刚刚编辑了你的。
        猜你喜欢
        • 1970-01-01
        • 2014-02-18
        • 2015-10-05
        • 2015-04-08
        • 1970-01-01
        • 1970-01-01
        • 2023-03-13
        • 2015-05-25
        • 1970-01-01
        相关资源
        最近更新 更多