我需要创建一个级联列表框,如下图中的图像,但每个列表框使用相同的数据列表,但使用不同的过滤器。 我有this code我可以用两个选项来完成它,但正如你所看到的,我使用两个observable来读取每个选择的de值。有没有办法使用foreach绑定创建这个,如果我可能需要10个选择,例如?
var ViewModel = function() {
self = this;
self.family = ko.mapping.fromJS(data.family);
self.selected = ko.observable();
self.selected2 = ko.observable();
self.filteredFamily = ko.computed(function() {
var list = ko.utils.arrayFilter(self.family(), function(item) {
if (self.selected() == undefined) return;
return item.parent() === self.selected().name();
});
return list;
});
}
var data = {
family: [{
name: "John",
parent: null
}, {
name: "Mike",
parent: null
}, {
name: "Alice",
parent: "John"
}, {
name: "Paul",
parent: "John"
}]
};
var viewModel = new ViewModel();
ko.applyBindings(viewModel);

<script src="https://cdnjs.cloudflare.com/ajax/libs/knockout/3.2.0/knockout-min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/knockout.mapping/2.4.1/knockout.mapping.min.js"></script>
<select data-bind="options: family, optionValue: name,optionsText: 'name',value:selected, optionsCaption: 'Choose...'"></select>
<select data-bind="options: filteredFamily, optionValue: name,optionsText: 'name',value:selected2, optionsCaption: 'Choose...'"></select>
&#13;
[增订]
抱歉,我认为我的问题没有很好地表达,我需要在列表框中选择一些内容时,下一个用最后一个lisbox的数据更新他的数据。答案 0 :(得分:0)
不确定。但是foreach需要一个(可观察的)数组,我建议将“小部件”代码封装在一个单独的视图模型中。这是一个天真的设置:
var SelectionViewModel = function(baseOptionsObsArray, filter) {
var self = this;
self.filteredOptions = ko.computed(function() {
var val = ko.utils.unwrapObservable(filter.val); // Allow observable and plain property
return baseOptionsObsArray().filter(function(opt) {
return ko.utils.unwrapObservable(opt[filter.prop]) === val;
});
});
self.filter = filter;
self.selected = ko.observable();
};
var ViewModel = function(data) {
var self = this;
self.family = ko.mapping.fromJS(data.family);
self.selectables = ko.observableArray([
new SelectionViewModel(self.family, { name: "No Parent", prop: "parent", val: null }),
new SelectionViewModel(self.family, { name: "Parent is John", prop: "parent", val: "John" }),
new SelectionViewModel(self.family, { name: "Has a pet", prop: "hasPet", val: true }),
new SelectionViewModel(self.family, { name: "Name is Alice", prop: "name", val: "Alice" }),
]);
};
var data = {
family: [{ name: "John", parent: null, hasPet: true },
{ name: "Mike", parent: null, hasPet: true },
{ name: "Alice", parent: "John", hasPet: false },
{ name: "Paul", parent: "John", hasPet: true }
]
};
ko.applyBindings(new ViewModel(data));
<script src="https://cdnjs.cloudflare.com/ajax/libs/knockout/3.2.0/knockout-min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/knockout.mapping/2.4.1/knockout.mapping.min.js"></script>
<!-- ko foreach: selectables -->
<span data-bind="text: filter.name"></span>
<select data-bind="options: filteredOptions,
optionValue: name,
optionsText: 'name',
value: selected,
optionsCaption: 'Choose...'"></select>
<hr>
<!-- /ko -->
您可以轻松添加诸如使用通配符,否定等更高级过滤之类的内容。这仍然是读者的练习。
在任何情况下,我认为您的问题(如何确保您可以轻松创建10个选项和过滤的选项列表)将得到解答。
另一方面,如果你正在寻找更多钻取样式的选择框,我仍然建议使用单独的视图模型并嵌套。 E.g:
var SelectionViewModel = function(parent, everyone) {
var self = this;
self.selection = ko.observable();
self.filteredOptions = everyone().filter(function(p) {
console.log(p);
if (!parent) { return !p.parent(); }
return p.parent() === parent.name();
});
self.subSelection = ko.computed(function() {
if (!self.selection()) { return null; }
return new SelectionViewModel(self.selection(), everyone);
});
};
var ViewModel = function(data) {
var self = this;
self.everyone = ko.mapping.fromJS(data.family);
self.familyHead = ko.observable(new SelectionViewModel(null, self.everyone));
};
var data = {
family: [{ name: "John", parent: null },
{ name: "Mike", parent: null },
{ name: "Alice", parent: "John" },
{ name: "Graaw", parent: "John" },
{ name: "Paul", parent: "John" },
{ name: "Marc", parent: "Alice" },
{ name: "Fika", parent: "Alice" },
{ name: "Eric", parent: "Marc" }
]
};
ko.applyBindings(new ViewModel(data));
<script src="https://cdnjs.cloudflare.com/ajax/libs/knockout/3.2.0/knockout-min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/knockout.mapping/2.4.1/knockout.mapping.min.js"></script>
<script type="text/html" id="selectable">
<select data-bind="options: filteredOptions,
optionValue: name,
optionsText: 'name',
value: selection,
optionsCaption: 'Choose...'"
size="5"></select>
<!-- ko with: subSelection -->
<!-- ko template: 'selectable' --><!-- /ko -->
<!-- /ko -->
</script>
<!-- ko template: { data: familyHead, name: 'selectable' } --><!-- /ko -->
答案 1 :(得分:0)
我发现了如何做到这一点。这就是我正在做的事情:
var ViewModel = function() {
self = this;
self.family = ko.mapping.fromJS(data.family);
self.selected = ko.observable();
self.filteredFamily = ko.computed(function() {
var list = ko.utils.arrayFilter(self.family(), function(item) {
debugger;
if (self.selected() == undefined) return;
return item.parent() === self.selected().name();
});
debugger;
return list;
});
}
var data = {
family: [{
name: "John",
parent: null
}, {
name: "Mike",
parent: null
}, {
name: "Alice",
parent: "John"
}, {
name: "Paul",
parent: "John"
}]
};
var viewModel = new ViewModel();
ko.applyBindings(viewModel);
<script src="https://cdnjs.cloudflare.com/ajax/libs/knockout/3.2.0/knockout-min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/knockout.mapping/2.4.1/knockout.mapping.min.js"></script>
<select data-bind="options: family, optionValue: name,optionsText: 'name',value:selected, optionsCaption: 'Choose...'"></select>
<select data-bind="options: filteredFamily, optionValue: name,optionsText: 'name',value:selected()[1], optionsCaption: 'Choose...'"></select>