【问题标题】:Filtering list items with ng-repeat from a selection/de-selection of a combination of checkboxes使用 ng-repeat 从复选框组合的选择/取消选择中过滤列表项
【发布时间】:2018-02-12 04:24:42
【问题描述】:

我有一个根据价格属性的变化经常更新的项目列表。如果某个项目的价格低于某个值(低于 5),则该项目的“selected”属性设置为 true 并显示在结果表中(根据 selected 属性过滤)。

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'}"

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

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

【问题讨论】:

    标签: angularjs checkbox filter


    【解决方案1】:

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

    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)连接它们:

    导航控制器:

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

    价格控制器:

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

    【讨论】:

    • 您好,谢谢。从概念上讲,我认为它很接近,但是当我用你的代码调整我的代码时它似乎不起作用 - 请参阅更新的 plunkr,plnkr.co/edit/WgHQj4rbU3jgMMHNh81i?p=preview
    • 非常感谢。我个人觉得我从中学到了很多东西!再次感谢:)
    【解决方案2】:

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

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

    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();。所以每次你选择一个新的尺寸过滤器或类似的东西时,你都需要执行代码。

    【讨论】:

      猜你喜欢
      • 2016-10-14
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2013-05-25
      • 2016-09-28
      • 1970-01-01
      • 1970-01-01
      • 2014-06-21
      相关资源
      最近更新 更多