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

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

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

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

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

Ответы

Ответ 1

Возможны несколько реализаций. Здесь один:

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

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

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

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


Функция filterByCategory может быть реализована следующим образом:

function filterByCategory(wine) {
  // Display the wine if
  var displayWine =
      // the wine 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]; });
}

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


UPDATE

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

  • Фильтрует каждый элемент wine, основываясь на каждом свойстве.
  • Если свойство не имеет фильтра (т.е. флажок не установлен), он игнорируется.
  • Если свойство имеет отмеченные флажки, оно используется для фильтрации элементов wine (см. выше).
  • Существует код для применения нескольких фильтров с использованием AND (т.е. все свойства должны совпадать) или OR (по крайней мере одно свойство должно соответствовать).

Смотрите также эту обновленную демонстрационную версию.

Ответ 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">