Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Select2 - Can’t select values from a multi-level tree

I have a multi-level Select2, divided in groups, subgroups and options. The expected behavior is that only options can be selected. For an unkonwn reason, only the first level childs can be selected (meaning values Option 1.1 and Option 1.2 in the code below):

$(function() {
  var theData = [{
      "id": "",
      "text": ""
    },
    {
      "text": "Group 1",
      "children": [{
          "id": 1,
          "text": "Option 1.1"
        },
        {
          "id": 2,
          "text": "Option 1.2"
        }
      ]
    },
    {
      "text": "Group 2",
      "children": [{
          "id": 3,
          "text": "Subgroup 2.1",
          "children": [{
              "id": 41,
              "text": "Option 2.1.1"
            },
            {
              "id": 42,
              "text": "Option 2.1.2"
            }
          ]
        },
      ]
    }
  ];
  $("#mySelect").select2({
    placeholder: "Select a option...",
    data: theData
  });
});

The HTML goes just like this

<select id="mySelect" class="form-control" style="width:400px;"></select>

I've made a fiddle to better demostrate this https://jsfiddle.net/zjy16uo9/. There you can see that only those two values can be selected.

like image 399
rodsarria Avatar asked May 04 '26 19:05

rodsarria


1 Answers

You have hit a limitation of HTML version 5 and below. <optgroup>s are not nestable, their only allowed parent is <select>.

Select2 docs warn against it:

Because Select2 generates an <optgroup> when creating nested options, only a single level of nesting is supported. Any additional levels of nesting is not guaranteed to be displayed properly across all browsers and devices.

Furthermore:

Hierarchical options

Only a single level of nesting is allowed per the HTML specification. If you nest an <optgroup> within another <optgroup>, Select2 will not be able to detect the extra level of nesting and errors may be triggered as a result.

Furthermore, <optgroup> elements cannot be made selectable. This is a limitation of the HTML specification and is not a limitation that Select2 can overcome.

If you wish to create a true hierarchy of selectable options, use an <option> instead of an <optgroup> and change the style with CSS. Please note that this approach may be considered "less accessible" as it relies on CSS styling, rather than the semantic meaning of <optgroup>, to generate the effect.


In practice/Demo

Select2, as said, renders a <select>. From your fiddle, you can get the one it renders by inspecting the DOM.

I copied the rendered DOM and pasted in the demo below.

Look how the nested <optgroup>s aren't really nested, no matter the level, they are rendered only one level deep.

$(function() {
  var theData = [{
      "id": "",
      "text": ""
    },
    {
      "text": "Group 1",
      "children": [{
          "id": 1,
          "text": "Option 1.1"
        },
        {
          "id": 2,
          "text": "Option 1.2"
        }
      ]
    },
    {
      "text": "Group 2",
      "children": [{
          "id": 3,
          "text": "Subgroup 2.1",
          "children": [{
              "id": 41,
              "text": "Option 2.1.1"
            },
            {
              "id": 42,
              "text": "Option 2.1.2"
            }
          ]
        },
        {
          "id": 4,
          "text": "Subgroup 2.2",
          "children": [{
              "id": 41,
              "text": "Subgroup 2.2.1",
              "children": [{
                "id": 41,
                "text": "Option 2.2.1.1"
              }]
            },
            {
              "id": 42,
              "text": "Subgroup 2.2.2",
              "children": [{
                  "id": 41,
                  "text": "Option 2.2.2.1"
                },
                {
                  "id": 42,
                  "text": "Option 2.2.2.2"
                }
              ]
            }
          ]
        }
      ]
    }
  ];
  $("#mySelect").select2({
    placeholder: "Select a option...",
    data: theData
  });
});
<script type="text/javascript" src="https://ajax.googleapis.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<script type="text/javascript" src="https://cdnjs.cloudflare.com/ajax/libs/select2/4.0.6-rc.0/js/select2.min.js"></script>
<link rel="stylesheet" type="text/css" href="https://cdnjs.cloudflare.com/ajax/libs/select2/4.0.6-rc.0/css/select2.min.css">

<select id="mySelect" class="form-control" style="width:400px;"></select>

<br>
<hr>
<br>
Notice how these nested optgroups are rendered as if they weren't nested at all. They are all only one level deep:<br>
<select>
    <option value="" data-select2-id="1"></option>
    <optgroup label="Group 1" data-select2-id="2">
        <option value="1" data-select2-id="3">Option 1.1</option>
        <option value="2" data-select2-id="4">Option 1.2</option>
    </optgroup>
    <optgroup label="Group 2" data-select2-id="5">
        <optgroup label="Subgroup 2.1" data-select2-id="6">
            <option value="41" data-select2-id="7">Option 2.1.1</option>
            <option value="42" data-select2-id="8">Option 2.1.2</option>
        </optgroup>
        <optgroup label="Subgroup 2.2" data-select2-id="9">
            <optgroup label="Subgroup 2.2.1" data-select2-id="10">
                <option value="41" data-select2-id="11">Option 2.2.1.1</option>
            </optgroup>
            <optgroup label="Subgroup 2.2.2" data-select2-id="12">
                <option value="41" data-select2-id="13">Option 2.2.2.1</option>
                <option value="42" data-select2-id="14">Option 2.2.2.2</option>
            </optgroup>
        </optgroup>
    </optgroup>
</select>

Workaround

I would follow the one suggested by Select2:

If you wish to create a true hierarchy of selectable options, use an <option> instead of an <optgroup> and change the style with CSS. Please note that this approach may be considered "less accessible" as it relies on CSS styling, rather than the semantic meaning of <optgroup>, to generate the effect.

like image 193
acdcjunior Avatar answered May 06 '26 10:05

acdcjunior



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!