想象一下有一系列葡萄酒:
[
{
"name":"wine A",
"category":[
"red",
"merlot"
]
},
{
"name":"wine B",
"category":[
"white",
"chardonnay"
]
},
{
"name":"wine C",
"category":[
"white",
"chardonnay",
"red",
"merlot"
]
}
]
我需要使用AngularJS创建过滤/分组机制,这样,如果用户选择“霞多丽”,结果将是:
Results: wine B, wine C
我有一个有效的示例,但是请检查该示例的结构数据。在对象项中未定义任何数组。我应该在控制器中进行哪些调整以使其与上述(数组)结构兼容?
var app = angular.module("myApp", []);
app.controller("myCtrl", 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.filter = {};
$scope.getOptionsFor = function(propName) {
return ($scope.wines || [])
.map(function(w) {
return w[propName];
})
.filter(function(w, idx, arr) {
return arr.indexOf(w) === idx;
});
};
$scope.filterByProperties = function(wine) {
// Use this snippet for matching with AND
var matchesAND = true;
for (var prop in $scope.filter) {
if (noSubFilter($scope.filter[prop])) continue;
if (!$scope.filter[prop][wine[prop]]) {
matchesAND = false;
break;
}
}
return matchesAND;
/**/
/*
// Use this snippet for matching with OR
var matchesOR = true;
for (var prop in $scope.filter) {
if (noSubFilter($scope.filter[prop])) continue;
if (!$scope.filter[prop][wine[prop]]) {
matchesOR = false;
} else {
matchesOR = true;
break;
}
}
return matchesOR;
/**/
};
function noSubFilter(subFilterObj) {
for (var key in subFilterObj) {
if (subFilterObj[key]) return false;
}
return true;
}
});
app.filter("capitalizeFirst", function() {
return function(str) {
str = str || "";
return str.substring(0, 1).toUpperCase() + str.substring(1).toLowerCase();
};
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/angular.js/1.7.5/angular.min.js"></script>
<div ng-app="myApp">
<div ng-controller="myCtrl">
<div ng-repeat="(prop, ignoredValue) in wines[0]" ng-init="filter[prop]={}">
<b>{{prop | capitalizeFirst}}:</b>
<br />
<span class="quarter" ng-repeat="opt in getOptionsFor(prop)">
<input type="checkbox" ng-model="filter[prop][opt]" /> {{opt}}
</span>
<hr>
</div>
<div ng-repeat="w in filtered=(wines | filter:filterByProperties)">
{{w.name}} ({{w.category}})
</div>
<hr> Number of results: {{filtered.length}}
</div>
</div>
答案 0 :(得分:0)
只需使用search
过滤器:
<b>Pick your category: (Hard coding)</b>
<ul>
<li style="cursor:pointer" ng-click="click_filter('red')">red</li>
<li style="cursor:pointer" ng-click="click_filter('merlot')">merlot</li>
<li style="cursor:pointer" ng-click="click_filter('white')">white</li>
<li style="cursor:pointer" ng-click="click_filter('chardonnay')">chardonnay</li>
</ul>
<b>Result</b>
<div ng-repeat="wine in wines | filter:search ">
<b>{{wine.name}}</b> - (category): {{wine.category}}
</div>
</div>
JS:
$scope.click_filter = function(item) {
$scope.search = item;
}
还有什么要做的(如果您不希望对类别进行硬编码)-寻找如何从ng-repeat中删除重复的条目(在我的朋克示例中,存在此问题)
答案 1 :(得分:0)
从列表移到数组时,您必须修改如何检索选项并添加对flat()的调用
$scope.getOptionsFor = function(propName) {
return ($scope.wines || [])
.map(function(w) {
return w[propName];
})
.flat()
.filter(function(w, idx, arr) {
return arr.indexOf(w) === idx;
});
};
然后filterByProperty需要能够处理数组以及纯值:
$scope.filterByProperties = function(wine) {
// Use this snippet for matching with AND
var matchesAND = true;
for (var prop in $scope.filter) {
if (noSubFilter($scope.filter[prop]))
continue;
if(Array.isArray(wine[prop])) {
let matchCount = 0;
for(let i in wine[prop]) {
if ($scope.filter[prop][wine[prop][i]]) {
++matchCount;
}
}
let trueFilter = 0
Object.values($scope.filter[prop]).forEach(element => {
if (element)
++trueFilter
});
matchesAND = matchCount == trueFilter;
if (! matchesAND)
break
}
else {
if (!$scope.filter[prop][wine[prop]]) {
matchesAND = false;
break;
}}
}
return matchesAND;
};