名前付きアイテムの配列があり、それぞれに名前付きアイテムの他の配列(ある種のツリー)が含まれています。両方の配列で名前によるフィルタリングを実装する必要があります。
したがって、最初の配列の各項目の名前を確認します。
- 名前が適切であれば、ブランチ全体を表示します。
- 名前が適切でない場合は、サブ配列をチェックしています:
- サブ配列に適切な名前の項目が含まれていない場合、ブランチは表示されません。
- サブ配列に適切な名前のアイテムが含まれている場合、適切なアイテムのみを含むブランチを表示します。
次の方法で実装しました。
ko.utils.stringStartsWith = function (string, startsWith) {
if (startsWith.length > string.length)
return false;
return string.substring(0, startsWith.length) === startsWith;
};
$(function () {
var vm = {
search: ko.observable(''),
items: ko.observableArray([])
};
//jsonData - my data
$.each(jsonData, function (i, jItem) {
var item = {
name: jItem.Name,
search: ko.observable(''),
subItems: ko.observableArray([])
};
$.each(jItem.Items, function (j, jsubItem) {
var subItem = {
name: jsubItem.Name,
};
item.subItems.push(subItem);
});
item.filteredSubItems = ko.computed(function () {
var self = this;
return ko.utils.arrayFilter(this.subItems(), function (fsubItem) {
if (self.search().length == 0
|| ko.utils.stringStartsWith(fsubItem.name.toLowerCase(), self.search().toLowerCase())) {
return true;
}
return false;
});
}, item);
vm.items.push(item);
});
vm.filteredItems = ko.computed(function () {
var self = this;
return ko.utils.arrayFilter(this.items(), function (fitem) {
if (self.search().length == 0
|| ko.utils.stringStartsWith(fitem.name.toLowerCase(), self.search().toLowerCase())) {
fitem.search('');
return true;
}
fitem.search(self.search());
if (fitem.filteredSubItems().length != 0)
return true;
return false;
});
}, vm);
ko.applyBindings(vm);
});
したがって、うまく機能しますが、の計算はfilteredItems
私にとって醜い回避策のように見えます。さらに、私は自分のソリューションのパフォーマンスを気にしています。
誰かがこれに対するより多くの解決策を知っていますか?