user3116167 user3116167 - 5 months ago 53
JSON Question

Filter by properties of nested array - Knockout

I have some problems filtering a nested array with Knockout out.

I want to be able to filter the array by 'tag-names' as well as 'name'.

i.e. type in 'whal' and all object that contain a tag with that name is filtered in grid.

Fiddle: 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());
})();

Answer

Just add a second check for the tags:

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;
                });

also check this fiddle