通过选择/取消选择复选框组合,使用ng-repeat过滤列表项

时间:2017-09-03 22:45:41

标签: angularjs checkbox filter

根据价格属性的变化,我有一个经常更新的项目列表。如果商品的价格低于某个值(低于5),则该商品会被选中' property设置为true并显示在结果表中(在所选属性上过滤)。

ng-repeat="item in dataPrices | filter: {selected:true}"

我想添加一系列复选框,基于所选复选框的选择/取消选择应该进一步过滤结果 - 可以选择零到三个

<label ng-click="productType('large')">
        <input type="checkbox">
        <span>Large items</span>
</label>
<label ng-click="productType('small')">
        <input type="checkbox">
        <span>Small items</span>
</label>
<label ng-click="productType('medium')">
        <input type="checkbox">
        <span>Medium items</span>
</label>

我确实尝试在ng-repeat

中添加一个额外的过滤器
ng-repeat="item in dataPrices | filter: {selected:true} | filter: {size:'large'}"

有效,但我不确定如何根据复选框选择/取消选择的组合结果添加这些组合。任何帮助都会非常感激。

我把这个笨蛋放在一起,这可能会让这个更清晰 - https://plnkr.co/edit/DHsOcWbfld7V7V1G8nIF?p=preview

2 个答案:

答案 0 :(得分:1)

您应该在内置oRfilter之后应用自定义filter : {selected: true}

angular.module('app', [])
.controller('ctrl', ['$scope', function($scope) {
    $scope.items = [
      {selected: true, size: 'large'},
      {selected: false, size: 'large'},
      {selected: false, size: 'medium'},
      {selected: true, size: 'medium'},
      {selected: true, size: 'small'}
    ];
    $scope.search = {};
}])
.filter('oRfilter', function(){
  return function(items, search){
    var out = [];    
    var atLeastOne = false;
    for(var prop in search)
      if(search[prop]){
        atLeastOne = true;
        out = out.concat(items.filter(function(x){ return x.size == prop; }));      
      }
    return atLeastOne ? out : items;
  }
})
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"></script>
<div ng-app="app" ng-controller="ctrl">
  <div ng-repeat='size in ["small", "medium", "large"]'>
    {{size}}: <input type='checkbox' ng-model='search[size]' />    
  </div>    
  <ul>
    <li ng-repeat='item in items | filter : {selected: true} | oRfilter : search'>{{item | json}}</li>
  </ul>
</div>

您的plunker不起作用,因为您有两个分隔的控制器。您应该通过事件(updated plunker):

连接它们

<强> navController:

$scope.$watchCollection('search', function(arg){
    $scope.$parent.$broadcast('changed', arg);
}); 

<强> priceController:

$scope.search = {};
$scope.$on('changed', function(event, arg){
    $scope.search = arg;
})

答案 1 :(得分:0)

如果你使用了很多额外的过滤器,它就不起作用,因为每个过滤器都应用于前一个过滤器的结果。 因此,如果您在执行此操作时选择“大”和“小”:{size:'large'},则结果不包含应用其他过滤器的“小”itens。

我认为你可以通过两种方式做到这一点。

1 - 您可以将函数返回到ng-repeat,它返回已过滤的列表:

 ng-repeat="item in filtered()"

在您的控制器中:

$scope.filtered = function() {
  //take the selected filter and your data and apply the filters
  //return the filtered list
  // you can code this with lodash
  // $scope.data -> your data
  // $scope.productType ->  can be one or multiple
  var filtered = _.filter($scope.data, function(item) {
      //Note that this filter is just an example, this implementation depends on what you really need and how your filter selection works.
      return item.selected && item.size === $scope.productType;
  });
  return filtered;
}

在这种情况下,您需要编写自己的过滤器并应用于列表。像lodash这样的图书馆可以为你提供很多帮助。

你也可以在ng-repeat中应用另一个过滤器:

ng-repeat="item in filtered() | anotherFilter"

2 - 您可以手动控制过滤器流量。这有点复杂,因为您需要准确了解视图应该如何工作以及何时需要更新视图。使用这种方法可以提高性能。

基本上,您将使用其他列表来接收过滤后的数据:

ng-repeat="item in filteredList"

当您需要调用函数(手动)来更新此列表时。所以

$scope.filteredList = getFilteredData();
function getFilteredData() {
  return _.filter($scope.data, function(item) {
      return item.selected && item.size === $scope.productType;
  });
}

请注意,在此方法中,每次要更新视图时都需要调用$scope.filteredList = getFilteredData();。因此,每次选择新的大小过滤器或类似的东西时,都需要执行代码。