Preload some data in a remote source dropdown

Ok so I have a page with several select2 dropdowns that each use a remote source JSON API endpoint (which I also built) for their content. We have a second API endpoint that has some suggested/likely options which we’d like to load into each dropdown on every page load, since it’s likely (almost guaranteed) that they’ll be used over the full search first option.

The only information I can find is how to load a single default using the “new Option” method but no matter what I do, I can’t figure out how to get more than the first option loaded.

The closest I’ve come is with this:

var thing = $('.thing');
var preload = $.ajax({
    type: 'GET',
    url: '/preload.json',
    dataType: 'json',
    success: function(data) {
        $.each(data, function(key, value){
            var option = new Option(value.text, value.id, false, false)
            thing.append(option).trigger('change');
            thing.trigger({
                type: 'select2:select',
                data: value
            })
        })
    }
});

Does anyone have any suggestions on how to do what I’m looking for, or am I hooped?

Are your dropdown’s multi-select, or single-select? I get the impression that they’re multi-selects, in which case you have to use a different method to programmatically select mutliple <option>s. See Selecting options in the Select2 documentation, especially the note about passing an array to the val() method before calling trigger('select2:change') to select multiple items.

You can “accumulate” the list of values inside your $.each() callback, which should only create your Option elements and append them to your select—not try to perform the selection. Then, after the $.each() call, you’ll have your array of values to select, which you can pass to Select2’s val() method, and then trigger the select2:change event.

Hi John,

No, it’s just a single select dropdown. Does that change your answer?

Yes, and my previous answer was wrong anyway. I overlooked that you’re retrieving the data via AJAX. In that case, you’re using the recommended method of inserting an option element containing your pre-selected value, but you’re not triggering the select2:select event correctly; or rather, you’re not passing the data to it correctly. You need to pass the data in the params.data property, not the data property. (Go review the documentation again, carefully, and you’ll see your mistake. Pay attention to the format of the object literal you’re passing to thing.trigger().)

Also, you mentioned that there are several selects that you’re trying to preload. Am I correct that you expect your thing variable to contain the jQuery collection of all of them? If so, that’s not what you’re iterating over. $.each()* iterates over the values in its first parameter (in your case, the data object returned by your $.ajax() call to fetch your preload items). Assuming the data object contains one key and one value for each of your select.things, then inside your “success” callback you should iterate over the thing collection (i.e., thing.each(function(index, selectElt) { ... });, and inside that callback insert an option containing the respective value from the data object into the current “selectElt” (which is one of the selects from the thing collection). (Note that your data object is visible to the .each()* callback even though it’s not directly passed into it, because it’s visible within that function’s enclosing scope.)

*Note: I realize that the difference between $.each() and collection.each() is confusing. I think that was a bad naming decision on jQuery’s part.

Without seeing the content of your data object (and also your HTML), it’s hard to fully diagnose the issue. If I were doing this, my preload data object would contain “key” values that match and ID or some other unique attribute of the selects, and the “value” value would be the desired pre-selected option for that select.

Can you share your preload data and your HTML, perhaps on codepen.io or jsfiddle.net?