Фильтр флажка 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">