Фильтр флажков AngularJS


Я хотел бы отфильтровать результаты.

Есть список вин, мое желание, когда не установлен флажок, отображается весь список вин.

  • Когда установлен только 1 флажок, отображается соответствующая категория
  • при установке нескольких флажков отображаются связанные категории

Я новичок в AngularJS, я попробовал с ng-моделью wihout success, вот код без ng-модели, связанной с функцией:

<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, чтобы связать функцию с каждой кнопкой флажка, чтобы иметь модель фильтрации в реальном времени??

2 18

2 ответа:

Я предпочитаю использовать 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">

Существует несколько возможных реализаций. Вот один из них:

  1. Есть объект $scope.filter = {} для хранения состояния каждого фильтра. Например, {red: true, white: false...}.

  2. Свяжите каждый флажок с соответствующим свойством, используя ng-model. Например: input type="checkbox" ng-model="filter['red']" />.

  3. Есть функция (например, $scope.filterByCategory(wine)), которая решает, следует ли отображать вино или нет (на основе объекта $scope.filter).

  4. Используйте эту функцию для фильтрации элементов по их категориям. Например. <div ng-repeat="wine in wines | filter:filterByCategory">


Функция 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]; });
}

См. также это короткая демонстрация.


Обновление :

Я создал модифицированную версию, которая поддерживает несколько фильтров (а не только фильтрацию по категориям).
В основном, он динамически обнаруживает доступные свойства (на основе первого элемента wine), добавляет элементы управления (группы флажков) для применения фильтров на основе каждого свойства и имеет пользовательскую функцию фильтра, которая:
  1. фильтрует каждый элемент wine, основываясь на каждом свойстве.
  2. если к свойству не применен фильтр (то есть не установлен флажок), оно игнорируется.
  3. Если свойство имеет флажки, то оно используется для фильтрации элементов wine (см. выше).
  4. существует код для применения несколько фильтров, использующих и (т. е. все свойства должны совпадать) или или (по крайней мере одно свойство должно совпадать).

См. также это обновленная демо-версия.