[英]Knockout.js: Using nested observables with mapping plugin
我正在構建一個側邊欄以過濾主視圖,例如John Lewis的側邊欄。 我的代碼正常工作,但效果不佳。
我知道在類似的行上有幾個SO問題,但是我不太了解自己的用例。
我需要從服務器(例如,通過JSON)獲取復選框的名稱,以便在ShopView上動態創建observableArrays。
情況如下:
var data = {
'gender' : [ ],
'color' : [ ]
};
var filterMapping = {
create: function( obj ) {
return ko.observableArray( obj.data );
}
}
var ShopView = new function() {
var self = this;
ko.mapping.fromJS( { filters: data }, filterMapping, self );
// this is the bit I don't like
this.filterChange = ko.computed(function () {
for( var key in self.filters ) {
var obj = self.filters[key];
if( ko.isObservable(obj)){
obj();
}
}
});
this.filterChange.subscribe( function( ) {
//make AJAX request for products using filter state
});
}
我的HTML外觀如您所願:
<ul>
<li><input type="checkbox" value="male" data-bind="checked: filters.gender" />Male</li>
<li><input type="checkbox" value="female" data-bind="checked: filters.gender" />Female</li>
</ul>
正如我說的那樣,它可以工作,但是效果不是很好。 在理想的世界中,我可以訂閱this.filters,例如
this.filters.subscribe( function() {
//make AJAX request for products using filter state
});
注意:我不打算在客戶端進行過濾-當動態綁定的復選框更改時,只需更新我的視圖模型即可。
有任何想法嗎? 謝謝!
首先,應將映射插件視為代碼復制的輔助工具。 我認為將映射插件本身視為解決方案並不是一個好主意。 至少不是直接。 由於我們看不到您正在使用的模型,因此它也會掩蓋您在SO上發布代碼時發生的情況。 只是一個想法。
現在,如果您想從服務器獲取動態過濾器,並使用它們來過濾項目列表(就像在商店中一樣),我會這樣做(在這里是小提琴 ):
var FilterOption = function(name) {
this.name = name;
this.value = ko.observable(false);
};
var Filter = function(data) {
var self = this;
self.name = data.name;
options = ko.utils.arrayMap(data.options, function(o) {
return new FilterOption(o);
});
self.options = ko.observableArray(options);
self.filteredOptions = ko.computed(function() {
var options = []
ko.utils.arrayForEach(self.options(), function(o) {
if (o.value()) options.push(o.name);
});
//If no options, false represents no filtering for this type
return options.length ? options : false;
});
};
var ViewModel = function(data) {
var self = this;
self.items = ko.observableArray(data.items);
filters = ko.utils.arrayMap(data.filters, function(i) {
return new Filter(i);
});
self.filters = ko.observableArray(filters);
self.filteredItems = ko.computed(function() {
//Get the filters that are actually active
var filters = ko.utils.arrayFilter(self.filters(), function(o) {
return o.filteredOptions();
});
//Remove items that don't pass all active filter
return ko.utils.arrayFilter(self.items(), function(item) {
var result = true;
ko.utils.arrayForEach(filters, function(filter) {
var val = item[filter.name.toLowerCase()];
result = filter.filteredOptions().indexOf(val) > -1;
});
return result;
});
});
};
下一步顯然是增加對具有多個屬性(但具有options屬性)的項目的支持,但這應該給您基本的思想。 您有一個過濾器列表,每個過濾器帶有任意數量的選項(累加堆疊),並且使用計算項目數組來存儲過濾項目的結果。
編輯 :要使用ajax訂閱獲取項目,您可以將FilteredItems
道具替換為獲取選定過濾器的計算對象,然后訂閱它,如下所示:
var ViewModel = function(data) {
var self = this;
self.items = ko.observableArray(data.items);
filters = ko.utils.arrayMap(data.filters, function(i) {
return new Filter(i);
});
self.filters = ko.observableArray(filters);
self.selectedFilters = ko.computed(function() {
ko.utils.arrayFilter(self.filters(), function(o) {
return o.filteredOptions();
});
});
self.selectedFilters.subscribe(function() {
//Ajax request that updates self.items()
});
};
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.