我在使用Knockout out过滤嵌套数组时遇到了一些问题。
我希望能够通过' tag-names'来过滤数组。以及' name'。
即。输入' whal'并且所有包含具有该名称的标记的对象都将在网格中过滤。
小提琴:https://jsfiddle.net/king_s/fj9L3wjz/3/
<input data-bind="value: searchQuery, valueUpdate: 'afterkeydown'" />
<div data-bind="foreach: filter" class="grid">
<p data-bind="text: name"></p>
</div>
(function(){
var ViewModel = function() {
var self = this;
var obj = { "id": 11,
"name": "mouse",
"tags": [{ "id": 1,
"name": "critter"
}]
};
var obj2 = { "id": 12,
"name": "dolphin",
"tags": [{ "id": 2,
"name": "fish"
},
{"id": 3,
"name": "whale"
}]
};
self.searchQuery = ko.observable("");
self.array = ko.observableArray([obj, obj2]);
self.filter = ko.computed(function() {
if(!self.searchQuery()) {
return self.array();
} else {
return ko.utils.arrayFilter(self.array(), function(obj) {
return obj.name.toLowerCase().indexOf(self.searchQuery().toLowerCase()) > -1;
});
}
});
};
ko.applyBindings(new ViewModel());
})();
答案 0 :(得分:2)
只需为标签添加第二次检查:
return ko.utils.arrayFilter(self.array(), function(obj) {
var tagsCheck = ko.utils.arrayFilter(obj.tags, function(tag) {
return tag['name'].toLowerCase().indexOf(self.searchQuery().toLowerCase()) > -1});
return (obj.name.toLowerCase().indexOf(self.searchQuery().toLowerCase()) > -1) || tagsCheck.length;
});
还要检查此fiddle
答案 1 :(得分:1)
你必须像这样迭代你的子对象:
self.filter = ko.computed(function() {
if (!self.searchQuery()) {
return self.array();
} else {
return ko.utils.arrayFilter(self.array(), function(obj) {
var value = obj.name.toLowerCase().indexOf(self.searchQuery().toLowerCase());
var compensation = 0; // Compensate for how many tags there are
obj.tags.forEach(function (tag) {
compensation--;
value += tag.name.toLowerCase().indexOf(self.searchQuery().toLowerCase());
})
// Final value is greater than -1 + (-1 * number of tags)
return value > -1 + compensation;
});
}
});
在这里试试fiddle
修改强>
我受到启发,更新了我对以下内容的回答,因此看起来更清晰:
self.filter = ko.computed(function() {
if (!self.searchQuery()) {
return self.array();
} else {
return ko.utils.arrayFilter(self.array(), function(obj) {
var found = obj.name.toLowerCase().indexOf(self.searchQuery().toLowerCase()) > -1;
obj.tags.forEach(function(tag) {
if (tag.name.toLowerCase().indexOf(self.searchQuery().toLowerCase()) > -1) {
found = true;
}
});
return found;
});
}
});
在这里试试fiddle
答案 2 :(得分:0)
我前一段时间制作了KO filters extender,这有助于完成这些工作。它在observableArray上创建一个filtered
属性,并允许灵活累积过滤器。
在您的HTML中,您可以:
<div data-bind="foreach: array.filtered" class="grid">
你的JS将是:
self.array = ko.observableArray([obj, obj2]).extend({filters: {
search: function(obj) {
var query = self.searchQuery().toLowerCase(),
nameMatch = obj.name.toLowerCase().match(query),
tagMatch = false;
obj.tags.forEach(function(tag, i) {
if (tag.name.toLowerCase().match(query))
tagMatch = true;
});
return nameMatch || tagMatch;
}
}});
self.array.toggleFilter('search', true);
请参阅updated fiddle。