如何在AngularJs中使用ng-repeat过滤(键,值)?


113

我正在尝试做类似的事情:

<div ng-controller="TestCtrl">
    <div ng-repeat="(k,v) in items | filter:hasSecurityId">
        {{k}} {{v.pos}}
    </div>
</div>

AngularJs部分:

function TestCtrl($scope) 
{
    $scope.items = {
                     'A2F0C7':{'secId':'12345', 'pos':'a20'},
                     'C8B3D1':{'pos':'b10'}
                   };

    $scope.hasSecurityId = function(k,v)
    {
       return v.hasOwnProperty('secId');
    }
}

但是不知何故,它向我展示了所有物品。如何筛选(键,值)?


请提供一些数据示例项目。还是给我们弄个小提琴;)
罗宾·德雷克斯勒

这不是您创建过滤器的方式,请参阅文档,正如Robin所说的,请举一个例子。
Yahya KACEM

我已经给出了完整的示例,并且我知道如何使用过滤器。我只是问“如何将过滤器与(键,值)一起使用”。
2013年

索引和计数应该在该范围内可用iirc
Shanimal

Answers:


131

Angular 过滤器只能通过angular的API应用于数组,而不能应用于对象-

“从数组中选择项的子集,并将其作为新数组返回。”

您在此处有两个选择:
1)移至$scope.items数组或
-2)预过滤ng-repeat项目,如下所示:

<div ng-repeat="(k,v) in filterSecId(items)">
    {{k}} {{v.pos}}
</div>

并在控制器上:

$scope.filterSecId = function(items) {
    var result = {};
    angular.forEach(items, function(value, key) {
        if (!value.hasOwnProperty('secId')) {
            result[key] = value;
        }
    });
    return result;
}

jsfiddlehttp : //jsfiddle.net/bmleite/WA2BE/


9
人们需要谨慎使用这种方法,以避免无限(消化)循环。参见6054705Narretz的摘要:简而言之,使用函数以ng-repeat返回集合是一种反模式。最好将集合分配给scope属性,并在其上循环。
Joe

3
有用的评论。这使我陷入困境。我希望能够过滤所有可迭代的对象。非常感谢。:)
克里斯·克里斯乔

3
注意:这是现在的perf反模式。Angular 1.3现在具有无状态过滤器(egghead.io/lessons/…),因此您一定要为此创建过滤器。
kentcdodds 2014年

8
@kentcdodds不会发布并非免费的链接!
塞巴斯蒂安

11
为什么不只在重复元素上添加ng-if?
CarbonDry 2015年

45

我的解决方案是创建自定义过滤器并使用它:

app.filter('with', function() {
  return function(items, field) {
        var result = {};
        angular.forEach(items, function(value, key) {
            if (!value.hasOwnProperty(field)) {
                result[key] = value;
            }
        });
        return result;
    };
});

并在html中:

 <div ng-repeat="(k,v) in items | with:'secId'">
        {{k}} {{v.pos}}
 </div>

1
但是,它将循环n * n次。
maxisam

27

你也可以使用ng-repeat具有ng-if

<div ng-repeat="(key, value) in order" ng-if="value > 0">

2
聪明。这样节省了很多时间。
萨夫万


11

您可以简单地使用angular.filter模块,然后甚至可以按嵌套属性进行过滤。
参见:jsbin
2示例:

JS:

angular.module('app', ['angular.filter'])
  .controller('MainCtrl', function($scope) {
  //your example data
  $scope.items = { 
    'A2F0C7':{ secId:'12345', pos:'a20' },
    'C8B3D1':{ pos:'b10' }
  };
  //more advantage example
  $scope.nestedItems = { 
    'A2F0C7':{
      details: { secId:'12345', pos:'a20' }
    },
    'C8B3D1':{
      details: { pos:'a20' }
    },
    'F5B3R1': { secId:'12345', pos:'a20' }
  };
});

HTML:

  <b>Example1:</b>
  <p ng-repeat="item in items | toArray: true | pick: 'secId'">
    {{ item.$key }}, {{ item }}
  </p>

  <b>Example2:</b>
  <p ng-repeat="item in nestedItems | toArray: true | pick: 'secId || details.secId' ">
    {{ item.$key }}, {{ item }}
  </p> 

21
您应该披露它angular.filter不是核心的角度模块,并且您是它的作者。
demisx

看起来toArray过滤器不再存在。是否存在替换项,因为filter过滤器仍然不允许对象?
trysis 2015年

6

有点晚了,但是我寻找了一个类似的过滤器,并最终使用了这样的东西:

<div ng-controller="TestCtrl">
 <div ng-repeat="(k,v) in items | filter:{secId: '!!'}">
   {{k}} {{v.pos}}
 </div>
</div>

2
您是如何使它工作的?当我将过滤器与ng重复对象一起使用时,会出现错误,这是基于Angular文档所期望的。
tonestrike

1

尽管这个问题比较老,但我还是想与有经验的1开发人员分享我的解决方案。关键是只重用原始的角度滤镜,而是透明地将任何对象作为数组传递。

app.filter('objectFilter', function ($filter) {
    return function (items, searchToken) {
        // use the original input
        var subject = items;

        if (typeof(items) == 'object' && !Array.isArray(items)) {
            // or use a wrapper array, if we have an object
            subject = [];

            for (var i in items) {
                subject.push(items[i]);
            }
        }

        // finally, apply the original angular filter
        return $filter('filter')(subject, searchToken);
    }
});

像这样使用它:

<div>
    <input ng-model="search" />
</div>
<div ng-repeat="item in test | objectFilter : search">
    {{item | json}}
</div>

这是一个小矮人


0

我做了一些已经在多个项目中使用过的通用过滤器:

  • object =需要过滤的对象
  • field =我们将在其上过滤的对象内的字段
  • filter =需要与该字段匹配的过滤器的值

HTML:

<input ng-model="customerNameFilter" />
<div ng-repeat="(key, value) in filter(customers, 'customerName', customerNameFilter" >
   <p>Number: {{value.customerNo}}</p>
   <p>Name: {{value.customerName}}</p>
</div>

JS:

  $scope.filter = function(object, field, filter) {
    if (!object) return {};
    if (!filter) return object;

    var filteredObject = {};
    Object.keys(object).forEach(function(key) {
      if (object[key][field] === filter) {
        filteredObject[key] = object[key];
      }
    });

    return filteredObject;
  };
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.