我需要使用嵌套对象来过滤数组,这意味着使用多个复选框来过滤数组,但是我遇到了重复名称的问题。 这是{I-I}一直在尝试使用的source code。
关于如何修复重复名称问题的任何想法?
HTML
<div data-ng-app="myApp">
<div data-ng-controller="controller">
<strong>Pick a brand to see the models</strong>
<div ng-init="group = (cars | groupBy:'make')">
<div ng-repeat="m in group">
<b><input type="checkbox" checked="true" ng-model="useMakes[$index]"/>{{m.name}}</b>
</div>
</div>
<br/>
<table border="1">
<thead>
<tr>
<th>#</th>
<th>Name</th>
<th>Maker</th>
</tr>
</thead>
<tbody>
<tr ng-repeat="car in cars | filter:filterMakes()">
<td>{{$index+1}}</td>
<td>{{car.make.name}}</td>
<td>{{car.model}}</td>
</tr>
</tbody>
JS
var myApp = angular.module('myApp',[]);
myApp.controller("controller", function($scope){
$scope.useMakes = [];
$scope.filterMakes = function () {
return function (p) {
for (var i in $scope.useMakes) {
if (p.make == $scope.group[i] && $scope.useMakes[i]) {
return true;
}
}
};
};
$scope.makes = [
{id:1, name: "BMV"},
{id:2, name: "Ford"},
{id:3, name: "Renault"},
{id:4, name: "Seat"},
{id:5, name: "Opel"}
];
$scope.cars = [
{model: '316', make: {id: 1, name: "BMV"}},
{model: '520', make: {id: 1, name: "BMV"}},
{model: 'Fiesta', make: {id: 2, name: "Ford"}},
{model: 'Focus', make: {id: 2, name: "Ford"}},
{model: 'Clio', make: {id: 3, name: "Renault"}},
{model: 'Toledo', make: {id: 4, name: "Seat"}},
{model: 'Leon', make: {id: 4, name: "Seat"}},
{model: 'Insignia', make: {id: 5, name: "Opel"}},
{model: 'Astra', make: {id: 5, name: "Opel"}},
{model: 'Corsa', make: {id: 5, name: "Opel"}}
];
});
/*I think here is the problem*/
var uniqueItems = function (data, key) {
var result = new Array();
for (var i = 0; i < data.length; i++) {
var value = data[i][key];
if (result.indexOf(value) == -1) {
result.push(value);
}
}
return result;
};
myApp.filter('groupBy', function () {
return function (collection, key) {
if (collection === null) return;
return uniqueItems(collection, key);
};
});
答案 0 :(得分:1)
您可以使用“唯一”过滤器
<div ng-repeat="m in group | unique:'name'">
<b><input type="checkbox" checked="true" ng-model="useMakes[$index]"/>{{m.name}}</b>
</div>
<强> DEMO 强>
答案 1 :(得分:1)
您可以使用AngularUI中的唯一过滤器(此处提供源代码:AngularUI unique filter)并直接在ng-options(或ng-repeat)中使用。
<select ng-model="orderProp" ng-options="place.category for place in places | unique:'category'">
<option value="0">Default</option>
// unique options from the categories
</select>
答案 2 :(得分:0)
问题的根源是当在indexOf
中使用uniqueItems()
时,对象引用(也称为内存地址)用于比较以检查数组中是否已存在某些内容。
uniqify的效果将不会按预期工作,因为$scope.cars[0].make
和$scope.cars[1].make
在两个不同的位置声明,因此将创建为2个不同的对象引用。
有两种可能的解决方案:
备选解决方案#1(首选):让make
中的每个$scope.cars
引用已在$scope.makes
中声明的对象。这是首选解决方案,因为您将有一个中心位置指定制作名称(Single Source Of Truth),即如果以后要将“BMV”修复为“BMW”,则只需要更改一个位置。
$scope.cars = [
{model: '316', make: $scope.makes[0]},
{model: '520', make: $scope.makes[0]},
{model: 'Fiesta', make: $scope.makes[1]},
{model: 'Focus', make: $scope.makes[1]},
{model: 'Clio', make: $scope.makes[2]},
{model: 'Toledo', make: $scope.makes[2]},
{model: 'Leon', make: $scope.makes[3]},
{model: 'Insignia', make: $scope.makes[4]},
{model: 'Astra', make: $scope.makes[4]},
{model: 'Corsa', make: $scope.makes[4]}
];
备选解决方案#2 :如果您出于某些原因想要保留$scope.cars
,我们需要修复$scope.filterMakes()
和uniqueItems()
以仅比较make
的唯一属性,而不是make
对象引用。在这种情况下,我们可以比较make.id
。
$scope.filterMakes = function () {
return function (p) {
for (var i in $scope.useMakes) {
if (p.make.id == $scope.group[i].id && $scope.useMakes[i]) { //add the ".id"
return true;
}
}
}
};
var uniqueItems = function (data, key) {
var result = new Array();
var added = []; //same as new Array();
for (var i = 0; i < data.length; i++) {
var value = data[i][key];
if (added.indexOf(value.id) == -1) { //look for the id
result.push(value);
added.push(value.id); //list of added ids
}
}
return result;
};