KnockoutJS - 使用 optgroup 和 javascript 对象绑定选择值
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/11189660/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
KnockoutJS - Binding value of select with optgroup and javascript objects
提问by user888734
I found an example hereto create a select list with optgroups using KnockoutJS. This works fine, but I want to bind the value of the dropdown to my own javascript object, then access a particular property of that object:
我在这里找到了一个示例,可以使用 KnockoutJS 创建带有 optgroups 的选择列表。这工作正常,但我想将下拉列表的值绑定到我自己的 javascript 对象,然后访问该对象的特定属性:
<select data-bind="foreach: groups, value:selectedOption">
<optgroup data-bind="attr: {label: label}, foreach: children">
<option data-bind="text: label"></option>
</optgroup>
</select>
function Group(label, children) {
this.label = ko.observable(label);
this.children = ko.observableArray(children);
}
function Option(label, property) {
this.label = ko.observable(label);
this.someOtherProperty = ko.observable(property);
}
var viewModel = {
groups: ko.observableArray([
new Group("Group 1", [
new Option("Option 1", "A"),
new Option("Option 2", "B"),
new Option("Option 3", "C")
]),
new Group("Group 2", [
new Option("Option 4", "D"),
new Option("Option 5", "E"),
new Option("Option 6", "F")
])
]),
selectedOption: ko.observable(),
specialProperty: ko.computed(function(){
this.selectedOption().someOtherProperty();
})
};
ko.applyBindings(viewModel);
?
?
回答by RP Niemeyer
A good choice for this situation is to create a quick custom binding that let's your "hand-made" options behave in the same way as options created by the options
binding (attaches the object as meta-data). The binding could simply look like:
对于这种情况,一个不错的选择是创建一个快速自定义绑定,让您的“手工制作”选项的行为方式与options
绑定创建的选项相同(将对象附加为元数据)。绑定可能看起来像:
ko.bindingHandlers.option = {
update: function(element, valueAccessor) {
var value = ko.utils.unwrapObservable(valueAccessor());
ko.selectExtensions.writeValue(element, value);
}
};
You would use it like:
你会像这样使用它:
<select data-bind="foreach: groups, value: selectedOption">
<optgroup data-bind="attr: {label: label}, foreach: children">
<option data-bind="text: label, option: $data"></option>
</optgroup>
</select>
Sample here: http://jsfiddle.net/rniemeyer/aCS7D/
回答by Berezh
This version with caption and if you want to have parent item selected:
此版本带有标题,如果您想选择父项:
<select data-bind="value: selectedOption ">
<option data-bind="value:'', text:'Select'"></option>
<!-- ko foreach: groups -->
<optgroup data-bind="attr:{label: label}">
<option data-bind="value: $data, text:label"></option>
<!-- ko foreach: children -->
<option data-bind="value: $data, text:label"></option>
<!-- /ko -->
</optgroup>
<!-- /ko -->
</select>
回答by Philip Bijker
If you want to have full control over the caption, groups and options and make this work with the value binding on the select element, you'll have to make sure all the options are bound before the select's value binding is bound. Otherwise the value binding will empty the selectedOption observable once the caption option is added.
如果您想完全控制标题、组和选项并使其与 select 元素上的值绑定一起使用,则必须确保在绑定 select 的值绑定之前绑定所有选项。否则,一旦添加了标题选项,值绑定将清空 selectedOption observable。
You could for example add a custom valueAfterChildren
binding, which wraps the value binding and makes sure the children are bound first. Have a look at the example below, which pre-selects "Option 5" on the slightly simplified viewmodel, before applying the bindings:
例如,您可以添加一个自定义valueAfterChildren
绑定,它包装值绑定并确保首先绑定孩子。看看下面的例子,在应用绑定之前,它在稍微简化的视图模型上预先选择了“选项 5”:
ko.bindingHandlers['valueAfterChildren'] = {
init: function(element, valueAccessor, allBindings, viewModel, bindingContext) {
ko.applyBindingsToDescendants(bindingContext, element);
ko.bindingHandlers['value'].init(element, valueAccessor, allBindings, viewModel, bindingContext);
return { controlsDescendantBindings: true };
},
value: function(element, valueAccessor, allBindings, viewModel, bindingContext) {
ko.bindingHandlers['value'].update(element, valueAccessor, allBindings, viewModel, bindingContext);
}
}
var viewModel = {
groups: [
{
label: "Group 1",
children: [{ label: "Option 1" }, { label: "Option 2" }, { label: "Option 3" }]
}, {
label: "Group 2",
children: [{ label: "Option 4" }, { label: "Option 5" }, { label: "Option 6" }]
}
],
selectedOption: ko.observable()
};
viewModel.selectedOption.subscribe(function(newVal) {
console.log(`selected ${!!newVal ? newVal.label : 'empty option'}`);
});
viewModel.selectedOption(viewModel.groups[1].children[1]);
ko.applyBindings(viewModel);
<script src="https://cdnjs.cloudflare.com/ajax/libs/knockout/3.4.2/knockout-min.js"></script>
<select data-bind="valueAfterChildren: selectedOption">
<option value="">Select</option>
<!-- ko foreach: groups -->
<optgroup data-bind="attr: {label: label}, foreach: children">
<option data-bind="value: $data, text: label"></option>
</optgroup>
<!-- /ko -->
</select>