1

I'm trying to bind a select/list box where i have 3 levels of data, i want my output to look like below

<select>
    <optgroup label="Root 1">
        <optgroup label="Group 1"> 
            <option>Option 1</option>
            <option>Option 2</option>
            <option>Option 3</option>
        </optgroup>
    </optgroup>
    <optgroup label="Root 2">
        <optgroup label="Group 2">
            <option>Option A</option>
            <option>Option B</option>
            <option>Option C</option>
        </optgroup>
    </optgroup>
</select>

And this is how I'm trying to bind

<div id="termdata">
    <select id="termsList" name="Term" data-bind="foreach: allterms">
        <optgroup data-bind="attr: { label: name}, foreach: termRoot">
            <optgroup data-bind="attr: { label: name},foreach: termGroup">
                <option data-bind="text: name"></option>
            </optgroup>                
        </optgroup>
    </select>
</div>

    var termData = [{
        "name": "Root 1", "termRoot": [{
            "name": "Group 1", "termGroup": [{
                "terms": [{
                    "name": "option 1"
                }, { "name": "option 2" }, { "name": "option 3" }]
            }]
        }]
    }, {
        "name": "Root 2", "termRoot": [{
            "name": "Group 2", "termGroup": [{
                "terms": [{
                    "name": "option A"
                }, { "name": "option B" }, { "name": "option C" }]
            }]
        }]
    }];

    var TermViewModel = function () {
        var self = this;
        self.allterms = ko.observableArray(termData);
    }

    ko.applyBindings(new TermViewModel(), document.querySelector('#termdata'));

I'm receiving following error

Message: Unable to process binding "foreach: function(){return terms }" Message: terms is not defined

whereas terms exists on groupTerms

Tauha
  • 99
  • 1
  • 12
  • 1
    Can you show your javascript? – Jason Spake Oct 19 '18 at 20:53
  • thanks for reply, i have updated the question – Tauha Oct 19 '18 at 21:47
  • It seems nesting option groups more than 1 level isn't supported in html. https://stackoverflow.com/questions/1037732/nesting-optgroups-in-a-dropdownlist-select – Jason Spake Oct 19 '18 at 22:08
  • thanks, yes i know, but i do not have alternate solution, if you see first example in my question nesting optgroup works, only problem is knockout is not supporting – Tauha Oct 19 '18 at 22:22

1 Answers1

2

From what I see you have invalid html loop syntax, and besides: nested optgroups are theoretically wrong and will be flattened anyway while rendering dom. This one should work:

<div id="termdata">
    <select id="termsList" name="Term" data-bind="foreach: allterms">
      <optgroup data-bind="attr: {label: name}"></optgroup>
      <!-- ko foreach: { data: termRoot, as: 'root' } -->
        <optgroup data-bind="attr: {label: root.name},
          foreach: { data: root.termGroup[0].terms, as: 'group' }">
          <option data-bind="text: group.name">ds</option>
        </optgroup>
      <!-- /ko -->
    </select>
</div>

Notice that termGroup is an Array, so theoretically you should loop over it as well (I've just used first index however - root.termGroup[0].terms), whereas you are trying to display termGroup.name in your syntax and there is no such thing since- as I said- termGroup is an Array.

Maciej Kwas
  • 6,169
  • 2
  • 27
  • 51
  • 1
    thanks, i spent one whole day to achieve it, but could not, i don't know further how much i saved, – Tauha Oct 23 '18 at 20:35