AngularJS - 通过在复选框中使用嵌套对象来过滤数组

时间:2016-10-27 00:07:43

标签: javascript angularjs

我需要使用嵌套对象来过滤数组,这意味着使用多个复选框来过滤数组,但是我遇到了重复名称的问题。 这是{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);
     };
});

3 个答案:

答案 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;
};