How can I set the initial value of Select2 when using AJAX?

You are doing most things correctly, it looks like the only problem you are hitting is that you are not triggering the change method after you are setting the new value. Without a change event, Select2 cannot know that the underlying value has changed so it will only display the placeholder. Changing your last part to

.val(initial_creditor_id).trigger('change');

Should fix your issue, and you should see the UI update right away.


This is assuming that you have an <option> already that has a value of initial_creditor_id. If you do not Select2, and the browser, will not actually be able to change the value, as there is no option to switch to, and Select2 will not detect the new value. I noticed that your <select> only contains a single option, the one for the placeholder, which means that you will need to create the new <option> manually.

var $option = $("<option selected></option>").val(initial_creditor_id).text("Whatever Select2 should display");

And then append it to the <select> that you initialized Select2 on. You may need to get the text from an external source, which is where initSelection used to come into play, which is still possible with Select2 4.0.0. Like a standard select, this means you are going to have to make the AJAX request to retrieve the value and then set the <option> text on the fly to adjust.

var $select = $('.creditor_select2');

$select.select2(/* ... */); // initialize Select2 and any events

var $option = $('<option selected>Loading...</option>').val(initial_creditor_id);

$select.append($option).trigger('change'); // append the option and update Select2

$.ajax({ // make the request for the selected data object
  type: 'GET',
  url: '/api/for/single/creditor/' + initial_creditor_id,
  dataType: 'json'
}).then(function (data) {
  // Here we should have the data object
  $option.text(data.text).val(data.id); // update the text that is displayed (and maybe even the value)
  $option.removeData(); // remove any caching data that might be associated
  $select.trigger('change'); // notify JavaScript components of possible changes
});

While this may look like a lot of code, this is exactly how you would do it for non-Select2 select boxes to ensure that all changes were made.


What I've done is more clean and needs to make two arrays :

  • one contains a list of Object with id and a text (in my case its id and name, depending of your templateResult) (its what you get from ajax query)
  • the second is only an array of ids (selection value)

I initialize select2 using the first array as data, and the second as the val.

An example function with as parameters a dict of id:name.

function initMyList(values) {
    var selected = [];
    var initials = [];

    for (var s in values) {
        initials.push({id: s, name: values[s].name});
        selected.push(s);
    }

    $('#myselect2').select2({
        data: initials,
        ajax: {
            url: "/path/to/value/",
            dataType: 'json',
            delay: 250,
            data: function (params) {
                return {
                    term: params.term,
                    page: params.page || 1,
                };
            },
            processResults: function (data, params) {
                params.page = params.page || 1;

                return {
                    results: data.items,
                    pagination: {
                        more: (params.page * 30) < data.total_count
                    }
                };
            },
            cache: true
        },
        minimumInputLength: 1,
        tokenSeparators: [",", " "],
        placeholder: "Select none, one or many values",
        templateResult: function (item) { return item.name; },
        templateSelection: function (item) { return item.name; },
        matcher: function(term, text) { return text.name.toUpperCase().indexOf(term.toUpperCase()) != -1; },
    });

    $('#myselect2').val(selected).trigger('change');
}

You can feed the initials value using ajax calls, and use jquery promises to do the select2 initialization.