30

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

</ p>

4

3 に答える 3

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/

于 2012-06-25T13:17:51.323 に答える
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>
于 2014-12-22T18:53:02.680 に答える
0

キャプション、グループ、およびオプションを完全に制御し、select要素の値バインディングでこれを機能させる場合は、selectの値バインディングがバインドされる前に、すべてのオプションがバインドされていることを確認する必要があります。それ以外の場合、キャプションオプションが追加されると、値バインディングはselectedOptionobservableを空にします。

たとえば、値のバインディングをラップし、子が最初にバインドさ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>

于 2019-12-13T15:05:17.970 に答える