简体   繁体   English

KnockoutJS - 选择与 optgroup 和 javascript 对象的绑定值

[英]KnockoutJS - Binding value of select with optgroup and javascript objects

I found an example here to create a select list with optgroups using KnockoutJS.我在这里找到了一个使用 KnockoutJS 创建带有 optgroups 的选择列表的示例。 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:这工作正常,但我想将下拉列表的值绑定到我自己的 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);

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).对于这种情况,一个不错的选择是创建一个快速自定义绑定,让您的“手工制作”选项的行为方式与options绑定创建的选项相同(将对象附加为元数据)。 The binding could simply look like:绑定可以简单地看起来像:

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/此处示例:http: //jsfiddle.net/rniemeyer/aCS7D/

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>

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.如果您想完全控制标题、组和选项,并使其与 select 元素上的值绑定一起使用,则必须确保在绑定 select 的值绑定之前绑定所有选项。 Otherwise the value binding will empty the selectedOption observable once the caption option is added.否则,一旦添加了标题选项,值绑定将清空 selectedOption observable。

You could for example add a custom valueAfterChildren binding, which wraps the value binding and makes sure the children are bound first .例如,您可以添加自定义valueAfterChildren绑定,它包装值绑定并确保首先绑定子项 Have a look at the example below, which pre-selects "Option 5" on the slightly simplified viewmodel, before applying the bindings:看看下面的例子,在应用绑定之前,它在稍微简化的视图模型上预先选择了“选项 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>

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM