Inserting optgroups into select field

Inserting optgroups into select field

rf1234rf1234 Posts: 2,988Questions: 87Answers: 421

I use this code to add optgroups to a select field's options:

editor
    .on('opened', function (e, mode, action) {
        $("#DTE_Field_report-report_type_id option").each(function(i) {
            if ( i == 0 ) {
                $(this).before("<optgroup label='1st group'>");
            } else if ( $(this).text().substr(0,2) == "09" ) {
                $(this).after("</optgroup><optgroup label='2nd group'>");
            } else if ( $(this).text().substr(0,2) == "23" ) {
                 $(this).after("</optgroup>");
            }
        });
    })

Surprisingly the ending tag </opgroup> is immediately added to the opt group so that it doesn't contain any options. I don't understand why this happens.

It looks like this:

Any idea how to fix this so that the two optgroups actually contain options.

This question has accepted answers - jump to:

Answers

  • allanallan Posts: 63,489Questions: 1Answers: 10,470 Site admin
    Answer ✓

    That's not working because you are attempting to manipulate the DOM like a string there. Line 5 creates a whole optgroup for example. Line 7 also creates a single optgroup and line 9 does nothing. You can check that out on the console:

    What you'd have to do is insert the two optgroups into the select and then move the option elements that you want into each one.

    I'd also suggest you do this only once (i.e. immediately after the options have loaded into Editor) rather than on every opened - otherwise you might end up adding many option groups!

    You can't just create new option elements as Editor adds custom properties to them to allow for strict typing of data.

    Allan

  • rf1234rf1234 Posts: 2,988Questions: 87Answers: 421

    What you'd have to do is insert the two optgroups into the select and then move the option elements that you want into each one.

    That sounds very cumbersome. I am loading the options from the server ...

    I'd also suggest you do this only once (i.e. immediately after the options have loaded into Editor) rather than on every opened - otherwise you might end up adding many option groups!

    Sure hadn't gotten that far when the question came up :smile:

    I chose a simple solution because it isn't really required that the options are within an optgroup. All I need is headings for the various groups of options.

    This is what I am using now:

    editor
        .one('opened', function (e, mode, action) {
            $("#DTE_Field_report-report_type_id option").each(function(i) {
                if ( i == 0 ) {
                    $(this).before("<optgroup label='1st group'>");
                } else if ( $(this).text().substr(0,2) == "09" ) {
                    $(this).after("<optgroup label='2nd group'>");
                }
            });
        })
    
  • allanallan Posts: 63,489Questions: 1Answers: 10,470 Site admin
    Answer ✓

    optgroups for the select are something I want to add support for in Editor in future! They really are useful for organising data :).

    Allan

  • rf1234rf1234 Posts: 2,988Questions: 87Answers: 421

    That would really be useful, Allan!

    I modified my solution and really move the options into the optgroups now. That was easier than I thought.

    I found this when googling:

    All you have to do is select the element(s) you want to move, then call an “adding” method such as append() , appendTo() or prepend() to add the selected elements to another parent element. jQuery automatically realises that the element(s) to add already exist in the page, and it moves the element(s) to the new parent.

    editor
        .one('opened', function (e, mode, action) {
            $("#DTE_Field_report-report_type_id option").each(function(i) {
                if ( i == 0 ) {
                    $(this).before("<optgroup label='1st group' id='1stgroup'>");
                } else if ( $(this).text().substr(0,2) == "09" ) {
                    $(this).after("<optgroup label='2nd group' id='2ndgroup'>");
                }
                if ( $(this).text().substr(0,2) <= "09" ) {
                    $(this).appendTo('#1stgroup');
                } else {
                    $(this).appendTo('#2ndgroup');
                }
            });
        })
    
  • rf1234rf1234 Posts: 2,988Questions: 87Answers: 421

    The solution above created issues when you do ajax.reloads of the data table. Suddenly you have empty optgroups and stuff like that.

    This is now my approach that also works when the table is reloaded from the server without page refresh.

    editor
        .on('opened', function (e, mode, action) {
            var optionsAdjusted = false;
            //do we have optgroups that are filled? => do nothing!
            $("#DTE_Field_report-report_type_id optgroup").each(function(i) {
                if ( $(this).children().length > 0 ) {
                    optionsAdjusted = true;
                    return false;
                }
            });
            if ( optionsAdjusted ) {
                return true; //we can stop here if we have adjusted options with optgroups
            }
            //remove empty optgroups (if there are any)
            $("#DTE_Field_report-report_type_id optgroup").each(function(i) {
                if ( $(this).children().length == 0 ) {
                    $(this).remove();
                }
            });
            //build the new optgroups with options inside
            optionsAdjusted = true;
            var oldReportType = "";
            var id = 0;
            $("#DTE_Field_report-report_type_id option").each(function(i) {
                if ( i == 0 ) {
                    return true;
                }
                var n = $(this).text().lastIndexOf("#");
                var reportType = $(this).text().substr(n + 1);
                $(this).text( $(this).text().substr(0, n) );
                if ( oldReportType != reportType ) {
                    id++;
                    $(this).before('<optgroup label="' + reportType + '"id="' + id + '">');
                    oldReportType = reportType;
                }
                $(this).appendTo('optgroup#' + id);
            });
        })
    
  • rf1234rf1234 Posts: 2,988Questions: 87Answers: 421
    edited September 2023

    @allan

    optgroups for the select are something I want to add support for in Editor in future! They really are useful for organising data :).

    Could you make those optgroups collapsible as well please.

    I have just implemented this using select2.

    This is what is looks like uncollapsed:

    And (partly) collapsed:

    This does the trick when using select2:

    $("body").on('click', '.select2-results__group', function() {
        $(this).siblings().toggle();
    });
    
  • allanallan Posts: 63,489Questions: 1Answers: 10,470 Site admin

    Could you make those optgroups collapsible as well please.

    I don't believe that is something that is built into the browser. For such a thing you'd need to use Select2 or similar.

    Allan

  • rf1234rf1234 Posts: 2,988Questions: 87Answers: 421

    No problem to do that if your select2 plugin allows the definition of outgroups within the Editor api.

Sign In or Register to comment.