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

时间:2012-06-25 12:46:25

标签: javascript jquery knockout.js

我找到了一个示例here来创建一个使用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);

3 个答案:

答案 0 :(得分:40)

这种情况的一个很好的选择是创建一个快速自定义绑定,让你的“手工制作”选项的行为与options绑定创建的选项相同(将对象作为元数据附加) 。绑定可能看起来像:

ko.bindingHandlers.option = {
    update: function(element, valueAccessor) {
       var value = ko.utils.unwrapObservable(valueAccessor());
       ko.selectExtensions.writeValue(element, value);   
    }        
};

您可以使用它:

<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>

此处示例:http://jsfiddle.net/rniemeyer/aCS7D/

答案 1 :(得分:10)

此版本带标题,如果您想要选择父项:

<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>

答案 2 :(得分:0)

如果要完全控制标题,组和选项,并使其与select元素上的值绑定一起使用,则必须确保在绑定select的值绑定之前,所有选项都已绑定。否则,一旦添加了标题选项,值绑定将清空selectedOption观察值。

例如,您可以添加一个自定义valueAfterChildren绑定,该绑定包装值绑定并确保children are bound first。看看下面的示例,该示例在应用绑定之前预先选择了稍微简化的viewmodel上的“选项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>