【问题标题】:KnockoutJS - Binding value of select with optgroup and javascript objectsKnockoutJS - 选择与 optgroup 和 javascript 对象的绑定值
【发布时间】:2012-06-26 17:27:54
【问题描述】:

我找到了一个示例 here 来使用 KnockoutJS 创建一个包含 optgroup 的选择列表。这很好用,但我想将下拉列表的值绑定到我自己的 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);

【问题讨论】:

    标签: javascript jquery knockout.js


    【解决方案1】:

    对于这种情况,一个不错的选择是创建一个快速的自定义绑定,让您的“手工”选项的行为方式与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/

    【讨论】:

    • 如何将“optionsCaption”添加到此解决方案中? @RP 尼迈耶
    • @SteW - 我想只是做一个简单的
    • 这不适用于预选选项(当 selectedOption 在绑定完成之前获取值时)
    【解决方案2】:

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

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

    【讨论】:

      【解决方案3】:

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

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

      【讨论】:

        猜你喜欢
        • 2012-09-30
        • 1970-01-01
        • 2012-10-09
        • 2014-08-14
        • 1970-01-01
        • 1970-01-01
        • 2023-03-12
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多