0

I have this select field:

<select data-bind="foreach: $root.feeGroups, value: $root.selectedFee">
     <optgroup data-bind="attr: {label: label}, foreach: fees">
           <option data-bind="text: description, option: $data"></option>
     </optgroup>
</select>

The feesGroup property:

 self.feeGroups([
        { label: "NEW", fees: self.fees().filter(f => f.status === "New") },
        { label: "OLD", fees: self.fees().filter(f => f.status === "Old") }
    ]);

And the binding handler:

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

My issue is with the "optionsCaption", as I am using a foreach method to generate the inner options it doesn't automatically work like it would if I was able to use the "Options" binding. But I do need to have a "Please Select..." default option.

Is there a way to do it?

user3378165
  • 6,546
  • 17
  • 62
  • 101

1 Answers1

1

You can move the foreach binding to a virtual element and add an extra option in your view that represents the null value:

<select data-bind="value: selectedFee">
  <option data-bind="text: 'Select an option', option: null"></option>
  <!-- ko foreach: feeGroups -->
  ...
  <!-- /ko -->
</select>

Keep in mind that the selectedFee observable will contain null when the placeholder is active.

// From: https://stackoverflow.com/a/11190148/3297291
ko.bindingHandlers.option = {
  update: function(element, valueAccessor) {
    var value = ko.utils.unwrapObservable(valueAccessor());
    ko.selectExtensions.writeValue(element, value);
  }
};

const fees = [
  { type: "old", description: "test1" },
  { type: "old", description: "test2" },
  { type: "new", description: "test3" },
  { type: "new", description: "test4" }
];

const feeGroups = [
  { label: "new", fees: fees.filter(f => f.type === "new") },
  { label: "old", fees: fees.filter(f => f.type === "old") }
];

const selectedFee = ko.observable(null);
selectedFee.subscribe(console.log.bind(console, "new selection:"));

ko.applyBindings({ feeGroups, selectedFee });
  
<script src="https://cdnjs.cloudflare.com/ajax/libs/knockout/3.4.2/knockout-min.js"></script>

<select data-bind="value: selectedFee">
  <option data-bind="text: 'Select an option', option: null"></option>
  <!-- ko foreach: feeGroups -->
    <optgroup data-bind="attr: {label: label}, foreach: fees">
        <option data-bind="text: description, option: $data"></option>
    </optgroup>
    <!-- /ko -->
</select>
user3297291
  • 22,592
  • 4
  • 29
  • 45