AngularJs删除ng-repeat中的重复元素

时间:2013-11-26 16:27:13

标签: angularjs angularjs-ng-repeat

我有一个存储在field_detail

中的字典
<li ng-repeat = "field in field_detail">{{field.displayName}}</li>

现在我不想包含displayName的重复field_detail,我应该使用哪个filter

5 个答案:

答案 0 :(得分:78)

只需创建一个过滤器,可以通过键获取唯一值。这样的事情应该做(我根本没有测试过,所以我会把这个事情留给你,这只是为了给你一个想法):

app.filter('unique', function() {
   return function(collection, keyname) {
      var output = [], 
          keys = [];

      angular.forEach(collection, function(item) {
          var key = item[keyname];
          if(keys.indexOf(key) === -1) {
              keys.push(key);
              output.push(item);
          }
      });

      return output;
   };
});
<div ng-repeat="item in items | unique: 'id'"></div>

注意:Array.indexOf()在IE8中不起作用,所以如果你支持IE8,你需要在indexOf()中存根,或者你需要使用一个方法略有不同。

其他想法:如果您已经引用了这些库,那么最好只创建一个利用lowdash或underscore中的唯一函数的过滤器。

答案 1 :(得分:14)

我根据Ben Leash提供的答案编写了一个JSFiddle:

http://jsfiddle.net/ThunderHemlock/bvsvzrr5/1/

谢谢,本。其他答案需要使用AngularJS UI或其他此类附加框架。

var app = angular.module('app', []);

app.filter('unique', function() {
   return function(collection, keyname) {
      var output = [], 
          keys = [];

      angular.forEach(collection, function(item) {
          var key = item[keyname];
          if(keys.indexOf(key) === -1) {
              keys.push(key);
              output.push(item);
          }
      });
      return output;
   };
});

app.controller('MyCtrl', function ($scope) {

$scope.items = [
      {
        id : 1,
        column : "col1",
        comment : "col1-label1",
        text1 : "col1-label1-text1",
        checked: false,

      },
      {
        id : 2,
        column : "col1",
        comment : "col1-label2",
        text1 : "col1-label2-text1",
        checked: false,

      },
      {
        id : 3,
        column : "col2",
        comment : "col2-label1",
        text1 : "col2-label1-text1",
        checked: false,

      },
      {
        id : 4,
        column : "col2",
        comment : "col2-label2",
        text1 : "col2-label2-text1",
        checked: false,

      },
      {
        id : 5,
        column : "col3",
        comment : "col3-label1",
        text1 : "col3-label1-text1",
        checked: false,

      },
      {
        id : 6,
        column : "col3",
        comment : "col3-label2",
        text1 : "col3-label2-text1",
        checked: false,

      },
      {
        id : 7,
        column : "col4",
        comment : "col4-label1",
        text1 : "col4-label1-text1",
        checked: false,

      },
      {
        id : 8,
        column : "col4",
        comment : "col4-label2",
        text1 : "col4-label2-text1",
        checked: false,

      }
      ];
    });



<div ng-app="app">
        <div ng-controller="MyCtrl as item">
            <ul>
                <li ng-repeat="item in items | unique: 'column'">
                    {{ item.column }}
                </li>
            </ul>
        </div>
    </div>

答案 2 :(得分:3)

为了搭载Ben Lesh,我添加了一个选项,如果键名是假的,则删除数组中的重复对象:

app.filter('unique', function () {
return function ( collection, keyname) {
    var output = [],
        keys = []
        found = [];

    if (!keyname) {

        angular.forEach(collection, function (row) {
            var is_found = false;
            angular.forEach(found, function (foundRow) {

                if (foundRow == row) {
                    is_found = true;                            
                }
            });

            if (is_found) { return; }
            found.push(row);
            output.push(row);

        });
    }
    else {

        angular.forEach(collection, function (row) {
            var item = row[keyname];
            if (item === null || item === undefined) return;
            if (keys.indexOf(item) === -1) {
                keys.push(item);
                output.push(row);
            }
        });
    }

    return output;
};
});

答案 3 :(得分:2)

我得到一张票据,当用户点击保存时,他们会收到一条错误,说明违反了唯一约束,等等等等。他们希望我的屏幕在数据库执行约束之前显示重复项。所以我写了一个函数来遍历对象数组的所有实例并计算它的实例。

$scope.anyDuplicates = function () {
    var dupes = false;
    for (var i = 0; i < $scope.kpiList.length; i++) {
        $scope.kpiList[i].cnt = 0;

        for (var j = 0; j < $scope.kpiList.length; j++) {

            if ($scope.kpiList[i].description == $scope.kpiList[j].description) {
                $scope.kpiList[i].cnt++;
            }

            if ($scope.kpiList[i].cnt > 1) dupes = true;
        }
    }
    return dupes;
}

...我在我的脚本中使用此函数来阻止保存,如下所示:

if ($scope.anyDuplicates()) { 
   alert('Duplicates Detected.  Please remove the duplicates before pressing the save button.'); 
} else { 
   save();
}

...并在添加新记录后立即向用户显示,如下所示:

$scope.kpiList.push({kpiId: newId, description: newDescription, new: true});
$scope.anyDuplicates();

...然后在我的HTML中,我有话要告诉用户副本在哪里......

<tr ng-repeat="row in kpiList | filter:searchText | orderBy:['kpiTypeId', 'description'] ">
<td>
   <span 
      ng-show="row.cnt > 1" 
      style="color: red; font-size: xx-small">
      duplicate
   </span>
</td>
...
</tr>

是的,我故意将每个实例与自身进行比较。这样的代码就少了。我查看是否.cnt&gt; 1代替&gt; 0

另外要注意...... kpiList.cnt字段在函数第一次运行之前不存在。 ng-show =&#34; row.cnt&gt; 1&#34;将表示错误(不是真实的),并且在row.cnt具有值之前不会显示。

此外,您应该使用StyleSheet格式化范围,而不是将其放在样式属性中。

答案 4 :(得分:1)

创建自己的功能:

productArray =[];
angular.forEach($scope.leadDetail, function(value,key){
var index = $scope.productArray.indexOf(value.Product);
if(index === -1)
{
    $scope.productArray.push(value.Product);
}

});