2017-01-24 56 views
1

我想通過多個屬性篩選結果。 我的代碼:AngularJS按屬性數組篩選項目(複選框)

(function() { 
 
    'use strict'; 
 
    angular. 
 
    module('myApp', []). 
 
    filter('byFeatures', byFeatures). 
 
    controller('MyCtrl', MyCtrl); 
 

 
    function byFeatures() { 
 
    return function (items, conditions) { 
 
     if (Object.getOwnPropertyNames(conditions).length === 0) { 
 
     return items; 
 
     } 
 
     var filtered = []; 
 
     for (var i = 0; i < items.length; i++) { 
 
     var item = items[i]; 
 
     angular.forEach(item.features, function (feature) { 
 
      if (conditions[feature.name] !== undefined && conditions[feature.name][feature.value] !== undefined) { 
 
      if (conditions[feature.name][feature.value]) { 
 
       //filtered.push(item); 
 
       filtered[item.id] = item; 
 
      } 
 
      } 
 
     }); 
 
     } 
 
     //console.log(filtered); 
 
     return filtered; 
 
    }; 
 
    }; 
 

 
    function MyCtrl($scope, $filter) { 
 
    $scope.allProducts = [{ 
 
     id: 0, 
 
     name: "Product A", 
 
     features: [{ 
 
      name: "Brand", 
 
      value: "Apple" 
 
      }, 
 
      { 
 
      name: "Memory", 
 
      value: "16" 
 
      }, 
 
      { 
 
      name: "Color", 
 
      value: "Black" 
 
      } 
 
     ] 
 
     }, 
 
     { 
 
     id: 1, 
 
     name: "Product B", 
 
     features: [{ 
 
      name: "Brand", 
 
      value: "Apple" 
 
      }, 
 
      { 
 
      name: "Memory", 
 
      value: "32" 
 
      }, 
 
      { 
 
      name: "Color", 
 
      value: "Black" 
 
      } 
 
     ] 
 
     }, 
 
     { 
 
     id: 2, 
 
     name: "Product C", 
 
     features: [{ 
 
      name: "Brand", 
 
      value: "Nokia" 
 
      }, 
 
      { 
 
      name: "Memory", 
 
      value: "16" 
 
      }, 
 
      { 
 
      name: "Color", 
 
      value: "Black" 
 
      } 
 
     ] 
 
     }, 
 
     { 
 
     id: 3, 
 
     name: "Product A", 
 
     features: [{ 
 
      name: "Brand", 
 
      value: "Samsung" 
 
      }, 
 
      { 
 
      name: "Memory", 
 
      value: "16" 
 
      }, 
 
      { 
 
      name: "Color", 
 
      value: "Black" 
 
      } 
 
     ] 
 
     }, 
 
    ]; 
 
    $scope.filters = [{ 
 
     name: "Brand", 
 
     values: [ 
 
      "Apple", 
 
      "Nokia", 
 
      "Samsung", 
 
     ] 
 
     }, 
 
     { 
 
     name: "Memory", 
 
     values: [ 
 
      "16", 
 
      "32", 
 
     ] 
 
     }, 
 
    ]; 
 
    $scope.currentFilter = {}; 
 
    $scope.$watch('currentFilter', function (newValue, oldValue, scope) { 
 
     //console.log(newValue); 
 

 
     $scope.products = $filter('byFeatures')($scope.allProducts, newValue); 
 
    }, true); 
 

 
    }; 
 
}());
<html> 
 
    <head> 
 
    <meta http-equiv="content-type" content="text/html; charset=UTF-8"> 
 
    <meta name="robots" content="noindex, nofollow"> 
 
    <meta name="googlebot" content="noindex, nofollow"> 
 
    <script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.4.8/angular.min.js"></script> 
 
    <title></title> 
 
</head> 
 

 
<body ng-app="myApp" class="ng-scope"> 
 
    <div ng-controller="MyCtrl" style="width: 100%;"> 
 
    
 
    <div style="width: 50%; float: left;"> 
 
     <h2>Available Phones</h2> 
 
     <div ng-repeat="product in products"> 
 
     <h3> 
 
      {{ product.name }} 
 
     </h3> 
 
     <ul> 
 
      <li ng-repeat="feature in product.features"> 
 
      {{feature.name}} : {{feature.value}} 
 
      </li> 
 
     </ul> 
 
     </div> 
 
    </div> 
 
    <div style="width: 50%; float: left;"> 
 
     <h2>Filters</h2> 
 
     <pre>{{currentFilter|json}}</pre> 
 
     <div ng-repeat="filter in filters"> 
 
     <span>{{filter.name}}</span> 
 
     <ul> 
 
      <li ng-repeat="value in filter.values"> 
 
      <input type="checkbox" ng-model="currentFilter[filter.name][value]"> {{value}}<br> 
 
      </li> 
 
     </ul> 
 
     </div> 
 
    </div> 
 
</div> 
 

 

 
</body></html>

如果我的品牌 「蘋果」 過濾器顯示2個手機與品牌 「蘋果」(16和32內存) - 其確定。但如果我通過內存「16」添加第二個過濾器 - 將只能顯示1個手機蘋果,內存爲「16」。 如何做到這一點? 。鏈接JSFiddle

回答

0

的問題是,你從你想要做的事情正好相反:您正在檢查該產品包含的項目(品牌存儲器)的一個有效的屬性。我們需要做的是檢查產品是否具有所有項目(品牌內存)的有效屬性。

只需改變函數內部的循環byFeatures就足以找到每個相關條件(當它的值爲真!)並確保我們的產品具有每個品牌和內存的所選屬性之一。在這裏你可以看到正確的片段:

(function() { 
 
    'use strict'; 
 
    angular. 
 
    module('myApp', []). 
 
    filter('byFeatures', byFeatures). 
 
    controller('MyCtrl', MyCtrl); 
 

 
    function byFeatures() { 
 
    return function (items, conditions) { 
 
     if (Object.getOwnPropertyNames(conditions).length === 0) { 
 
     return items; 
 
     } 
 
     var filtered = []; 
 
     for (var i = 0; i < items.length; i++) { 
 
     var item = items[i], 
 
      hasProperties = true; 
 

 
     angular.forEach(conditions, function (value, key) { 
 
      for (var i = 0; i < item.features.length; i++) { 
 
      if (item.features[i].name === key && (!value.hasOwnProperty(item.features[i].value) || !value[item.features[i].value])) { 
 
       for (var j in value) { 
 
       if (value[j]) { 
 
        hasProperties = false; 
 
       } 
 
       } 
 
      } 
 
      } 
 
     }); 
 

 
     if (hasProperties) { 
 
      filtered.push(item); 
 
     } 
 
     } 
 
     //console.log(filtered); 
 
     return filtered; 
 
    }; 
 
    }; 
 

 
    function MyCtrl($scope, $filter) { 
 
    $scope.allProducts = [{ 
 
     id: 0, 
 
     name: "Product A", 
 
     features: [{ 
 
      name: "Brand", 
 
      value: "Apple" 
 
      }, 
 
      { 
 
      name: "Memory", 
 
      value: "16" 
 
      }, 
 
      { 
 
      name: "Color", 
 
      value: "Black" 
 
      } 
 
     ] 
 
     }, 
 
     { 
 
     id: 1, 
 
     name: "Product B", 
 
     features: [{ 
 
      name: "Brand", 
 
      value: "Apple" 
 
      }, 
 
      { 
 
      name: "Memory", 
 
      value: "32" 
 
      }, 
 
      { 
 
      name: "Color", 
 
      value: "Black" 
 
      } 
 
     ] 
 
     }, 
 
     { 
 
     id: 2, 
 
     name: "Product C", 
 
     features: [{ 
 
      name: "Brand", 
 
      value: "Nokia" 
 
      }, 
 
      { 
 
      name: "Memory", 
 
      value: "16" 
 
      }, 
 
      { 
 
      name: "Color", 
 
      value: "Black" 
 
      } 
 
     ] 
 
     }, 
 
     { 
 
     id: 3, 
 
     name: "Product A", 
 
     features: [{ 
 
      name: "Brand", 
 
      value: "Samsung" 
 
      }, 
 
      { 
 
      name: "Memory", 
 
      value: "16" 
 
      }, 
 
      { 
 
      name: "Color", 
 
      value: "Black" 
 
      } 
 
     ] 
 
     }, 
 
    ]; 
 
    $scope.filters = [{ 
 
     name: "Brand", 
 
     values: [ 
 
      "Apple", 
 
      "Nokia", 
 
      "Samsung", 
 
     ] 
 
     }, 
 
     { 
 
     name: "Memory", 
 
     values: [ 
 
      "16", 
 
      "32", 
 
     ] 
 
     }, 
 
    ]; 
 
    $scope.currentFilter = {}; //$scope.filters; 
 
    $scope.$watch('currentFilter', function (newValue, oldValue, scope) { 
 
     $scope.products = $filter('byFeatures')($scope.allProducts, newValue); 
 
    }, true); 
 

 
    }; 
 
}());
<html> 
 

 
<head> 
 
    <meta http-equiv="content-type" content="text/html; charset=UTF-8"> 
 
    <meta name="robots" content="noindex, nofollow"> 
 
    <meta name="googlebot" content="noindex, nofollow"> 
 
    <script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.4.8/angular.min.js"></script> 
 
    <script src="js/script.js"></script> 
 
    <title></title> 
 
</head> 
 

 
<body ng-app="myApp" class="ng-scope"> 
 
    <div ng-controller="MyCtrl" style="width: 100%;"> 
 
    <div style="width: 50%; float: left;"> 
 
     <h2>Available Phones</h2> 
 
     <div ng-repeat="product in products"> 
 
     <h3> 
 
      {{ product.name }} 
 
     </h3> 
 
     <ul> 
 
      <li ng-repeat="feature in product.features"> 
 
      {{feature.name}} : {{feature.value}} 
 
      </li> 
 
     </ul> 
 
     </div> 
 
    </div> 
 
    <div style="width: 50%; float: left;"> 
 
     <h2>Filters</h2> 
 
     <pre>{{currentFilter|json}}</pre> 
 
     <div ng-repeat="filter in filters"> 
 
     <span>{{filter.name}}</span> 
 
     <ul> 
 
      <li ng-repeat="value in filter.values"> 
 
      <input type="checkbox" ng-model="currentFilter[filter.name][value]"> {{value}}<br> 
 
      </li> 
 
     </ul> 
 
     </div> 
 
    </div> 
 
    </div> 
 
</body> 
 

 
</html>

我也改變你添加新的產品,以過濾的陣列的方式。否則,如果唯一項目的ID是2,則陣列會將前2個位置保留爲'未定義',這會通過ngRepeat迭代