user9645
user9645

Reputation: 6806

How to update a multi-select and have it actually show the new options in Chrome

I can't believe it but I found some JS code that works perfectly in IE 11 but does not work in Chrome (version 81).

I am updating one multi select from another, keeping the options sorted. So I have a function for it:

    /**
     * Move the options defined by <sel> from select tag <from> to select tag <to>
     * @param from   The source SELECT tag jQuery object
     * @param to     The destination SELECT tag jQuery object
     * @param sel    Either: "option" for all, or "option:selected"
     */
    function moveOpt(from, to, sel) {
        var opts = from.children(sel).removeAttr('selected').remove().get();
        opts = opts.concat(to.children('option').remove().get());
        opts.sort(function (a, b) {
            return a.value.localeCompare(b.value);
        });
        to.append(opts);
        /*
        // Chrome doesn't re-render the opts until they are selected and then focus is lost ???
        window.setTimeout(function() {
            to.children('option').attr('selected', 'selected').trigger('click');
            from.trigger('focus');
            to.children('option').removeAttr('selected');
        }, 1);
         */
    }

This works perfectly in IE 11, but in chrome, the options get moved, but you can't see them in the browser. They are there because if you "inspect" the SELECT element, all the OPTION tags are there, and also doing $(to).children().length shows the correct number.

If I uncomment the ugly HACK (the window.setTimeout() call) then Chrome finally will show the options correctly. But it is NUTS to have to do this. I must be doing something wrong. Anyone know what that something is?

Here is a JS fiddle showing the issue - Running it in IE (read-only mode) shows it working, Chrome does not.

UPDATE

I tried upgrading jQuery from 1.10.2 to 3.5.0 and still did not work.

Also as @ZacharyYaro points out it works in Chrome 80 but not 81.

Changing this:

to.append(opts);

To this:

var toElm = to.get()[0];
$.each(opts, function(i,v) { toElm.appendChild(v); });

Fixes the problem.

Upvotes: 3

Views: 672

Answers (1)

Zachary Yaro
Zachary Yaro

Reputation: 306

(Resubmitting my comment as an answer since it worked for you) It appears your Fiddle also works in Chrome 80, and then breaks in Chrome 81. It appears using the built-in selectElement.add function instead of jQuery (JSFiddle) works in Chrome 81, so it seems Chrome 81 just broke something used by jQuery's $element.append(arrayOfElements) function.

Upvotes: 1

Related Questions