Use optgroup with knockout.js

I'm trying to manually display options inside optgroups in knockout.js, with guidance from Ryan Niemeyer's answer here . It works great, but only if the options are displayed immediately. If they are loaded subsequently, the correct item will not be selected.

Below is the code and script. Change

t: ko.observable(null)

      

to

t: ko.observable(t)

      

makes it work, so the issue is definitely load latency and I have ValueAllowUnset set to true.

script: http://jsfiddle.net/exyy7hq2/3/

Html

<select data-bind="template: { name: 'selectTemplateType', data: t }, valueAllowUnset: true, value: selectedId"></select>
<div data-bind='text: selectedId'></div>

<script type="text/html" id="selectTemplateType">
    <!-- ko ifnot: $data -->
        <option>No template selected</option>
    <!-- /ko -->
    <!-- ko if: $data -->
        <option>Select</option>
        <!-- ko foreach: groups -->
            <optgroup data-bind="attr: { 'label': name }, foreach: types">
                <option data-bind="option: id, text: name"></option>
            </optgroup>
        <!-- /ko -->
    <!-- /ko -->
</script>

      

JavaScript

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

var t = {
    groups: [
        { name: 'a', types: [{id: 1, name: 't1'}] },
        { name: 'b', types: [{id: 102, name: 't2'}, {id: 103, name: 't3'}] },
        { name: 'c', types: [{id: 5, name: 'x'}] }
    ]
}
var vm = {
    t: ko.observable(null),
    selectedId: ko.observable(103)
};
ko.applyBindings(vm);
setTimeout(function(){ vm.t(t); }, 2000);

      

+3


source to share


1 answer


It seems that if you are not using parameter bindings, Knockout simply has no way of adjusting when you dynamically generate new parameters, even when valueAllowUnset

set to true, so my approach just won't work; the correct parameters should be there when linked. One decent way to achieve this is to display select

only after the values ​​are present, as shown below (and also no optional custom binding is required - just binding to the default values ​​of the option element).

http://jsfiddle.net/exyy7hq2/11/



<!-- ko if: t -->
<select data-bind="template: { name: 'selectTemplateType', data: t }, value: selectedId"></select>
<!-- /ko -->
<!-- ko ifnot: t -->
<select>
    <option>No templates loaded</option>
</select>
<!-- /ko -->
<div data-bind='text: selectedId'></div>

<script type="text/html" id="selectTemplateType">
    <option>Select</option>
    <!-- ko foreach: groups -->
        <optgroup data-bind="attr: { 'label': name }, foreach: types">
            <option data-bind="value: id, text: name"></option>
        </optgroup>
    <!-- /ko -->
</script>

      

0


source







All Articles