【问题标题】:AngularJS checkbox filterAngularJS 复选框过滤器
【发布时间】:2014-07-21 21:49:10
【问题描述】:

我想过滤结果。

有一个酒单,我的愿望是当没有选中复选框时,显示整个酒单。

  • 仅选中 1 个复选框时显示相关类别
  • 选中多个复选框时,将显示相关类别

我是 AngularJS 的新手,我尝试使用 ng-model 没有成功,这里是没有 ng-model 的代码与函数关联:

<html ng-app="exampleApp">
<head>
    <title></title>
    <script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.3.0-beta.10/angular.min.js"></script>

    <script>
        angular.module("exampleApp", [])
                .controller("defaultCtrl", function ($scope) {
                    $scope.wines = [
                        { name: "Wine A", category: "red" },
                        { name: "Wine B", category: "red" },
                        { name: "wine C", category: "white" },
                        { name: "Wine D", category: "red" },
                        { name: "Wine E", category: "red" },
                        { name: "wine F", category: "white" },
                        { name: "wine G", category: "champagne"},
                        { name: "wine H", category: "champagne" }

                    ];


                    $scope.selectItems = function (item) {
                        return item.category == "red";
                    };

                    $scope.selectItems = function (item) {
                        return item.category == "white";
                    };

                    $scope.selectItems = function (item) {
                        return item.category == "champagne";
                    };
                });
    </script>
</head>
<body ng-controller="defaultCtrl">

<h4>red: <input type="checkbox"></h4>
<h4>white: <input type="checkbox"></h4>
<h4>champagne: <input type="checkbox"></h4>



            <div ng-repeat="w in wines | filter:selectItems">
                {{w.name}}
                {{w.category}}
            </div>


</body>
</html>

如何使用 ng-model 或 ng-change 将功能与每个复选框按钮关联起来以具有实时过滤模型??

【问题讨论】:

    标签: angularjs checkbox angularjs-directive angular-ngmodel angular-filters


    【解决方案1】:

    有几种可能的实现方式。这是一个:

    1. 有一个$scope.filter = {} 对象来保存每个过滤器的状态。例如。 {red: true, white: false...}.

    2. 使用ng-model 将每个复选框与相应的属性相关联。例如:input type="checkbox" ng-model="filter['red']" /&gt;

    3. 有一个函数(例如$scope.filterByCategory(wine))决定是否显示葡萄酒(基于$scope.filter 对象)。

    4. 使用该函数根据项目的类别过滤项目。例如。 &lt;div ng-repeat="wine in wines | filter:filterByCategory"&gt;


    filterByCategory 函数可以这样实现:

    function filterByCategory(wine) {
      // Display the wine if
      var displayWine =
          // the wine's category checkbox is checked (`filter[category]` is true)
          $scope.filter[wine.category] ||   // or 
    
          // no checkbox is checked (all `filter[...]` are false)
          noFilter($scope.filter);
    
      return displayWine;
    };
    

    其中noFilter() 是一个检查是否有任何过滤器被激活的函数(如果没有则返回true):

    function noFilter(filterObj) {
      return Object.
        keys(filterObj).
        every(function (key) { return !filterObj[key]; });
    }
    

    另请参阅此short demo


    更新

    我创建了一个修改版本,它支持多个过滤器(不仅仅是按类别过滤)。
    基本上,它动态检测可用属性(基于第一个 wine 元素),添加控件(复选框组)以根据每个属性应用过滤器,并具有自定义过滤器功能:

    1. 根据每个属性过滤每个 wine 项。
    2. 如果属性未应用过滤器(即未选中复选框),则会被忽略。
    3. 如果属性选中了复选框,则它用于过滤掉wine 项(见上文)。
    4. 有代码可以使用 AND(即所有属性必须匹配)或 OR(至少一个属性必须匹配)来应用多个过滤器。

    另请参阅此updated demo

    【讨论】:

    • ExpertSystem,非常感谢您的回答!!它对我更好地理解 AngularJS 有很大帮助。我会研究你的代码。真的,非常好的解决方案,再次感谢您分享您的知识!
    • 嗨 ExpertSystem,使用 $http.get 使用 json 文件加载数据,一切正常,但在 console.log 中有:TypeError:无法读取未定义的属性“地图”。最后一件事,如何放置过滤后的葡萄酒数量的动态计数器?问候!!
    • @Stéphane:看看更新的小提琴。我添加了对最初未定义的 wines 的支持并计算过滤后的葡萄酒。
    • @Stéphane:看看我更新的答案(和演示)。我不确定我明白你的意思(但希望我明白了)。顺便说一句,是的,我住在希腊:)
    • 这真的很有用。我一直在寻找这样的东西一段时间。您是否可以创建一个演示,说明如何使用它来包含范围过滤器以及例如通过一组预定义的价格范围选项进行过滤,例如0-100、100-200、200-300 和 300+
    【解决方案2】:

    只是添加到@gkalpak 答案中,我发现了这个codepen,它允许您提供为每个类别选择一个选项后剩余的总金额。

    ng-repeat 更改为:

    <div ng-repeat="wine in (ctrl.wines | filter:ctrl.filterByProperties) as filteredWines">
          {{ wine.name }} <i>({{ wine.category }})</i>
    </div>
    

    <div ng-repeat="wine in filtered = (ctrl.wines | filter:ctrl.filterByProperties) as filteredWines">
      {{ wine.name }} <i>({{ wine.category }})</i>
    </div>
    

    并使用输入标签添加:

    <label>
        <input type="checkbox" ng-model="ctrl.filter[prop][value]" />
        {{ value }}({{(filtered | filter:value:true).length}})
    </label>
    

    【讨论】:

      【解决方案3】:

      我更喜欢将filter 用作$filter

      app.filter('someFilter',checkboxFilter)
      checkboxFilter() {
          return function (arr,filter,key,noOne=false) {
              // arr is an array of objects
              // filter is checkbox filter. someting like {1:true,2:false}
              // key is a property in ech object inside arr
              // noOne is a behavior if none of checkbox is activated (default:false)
              if (!arr.length) return null;
      
              function noOneCheck(filter) {
                  return Object.keys(filter).every((key) => {
                      return !filter[key]
                  })
              }
              return arr.filter((i) => {
                  return filter[i[key]] || (noOne && noOneCheck(filter))
              })
          }
      };
      

      html:

      ng-repeat="u in project.projectTeamInvite | checkbox:project.status:'status' track by $index">
      

      【讨论】:

      • 哇! @Stéphane,您是否在 3 年多后更改了已接受的答案?
      猜你喜欢
      • 1970-01-01
      • 2013-12-30
      • 1970-01-01
      • 2019-02-17
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2016-12-06
      相关资源
      最近更新 更多