Bootstrap Multiselect update option list on flow

I use bootstrap multi-select and I want to update options on flow with ajax

To populate on init my multiselect I do

<select name="model" class="multiselect" multiple="multiple">
                <? foreach ($sel_models as $mod) { ?>
                    <option value="<?= $mod ?>" <?= ($mod == $params['model']) ? 'selected' : '' ?>><?= $mod ?></option>
                <? } ?>    
</select>  

then on event I would like to update my option list with the following ajax

I was trying to use the rebuild method but won't fire the drop-down after creation

 $.ajax({
        type: 'post',
        url: "helper/ajax_search.php",
        data: {models: decodeURIComponent(brands)},
        dataType: 'json',
        success: function(data) {
            $('select.multiselect').empty();
            $('select.multiselect').append(
                    $('<option></option>')
                    .text('alle')
                    .val('alle')
                    );

            $.each(data, function(index, html) {
                $('select.multiselect').append(
                        $('<option></option>')
                        .text(html.name)
                        .val(html.name)
                        );
            });

            $('.multiselect').multiselect('rebuild')
        },
        error: function(error) {
            console.log("Error:");
            console.log(error);
        }
    });

With firebug I can see that the list is generated but on select won't show up

Answers:

Answer

In the doc I can read :

.multiselect('setOptions', options) Used to change configuration after initializing the multiselect. This may be useful in combination with .multiselect('rebuild').

Maybe you can't change your widget data by your initial way. In a correct way you should use setOptions method.

Else : With your way, maybe should you think about destroy your widget .multiselect('destroy') and create it again after.

Update after comment :

In the doc : ( you've linked )

Provides data for building the select's options the following way:

var data = [
    {label: "ACNP", value: "ACNP"},
    {label: "test", value: "test"}
];
$("#multiselect").multiselect('dataprovider', data);

So : When you get data from your ajax call, you have to create an array of objects ( it's the options in the select you want to have ) with the format like

var data = 
[
    {label: 'option1Label', value: 'option1Value'},
    {label: 'option2Label', value: 'option2Value'},
    ...
]

When your objects array is created, then you just have to call the method

$("#multiselect").multiselect('dataprovider', data);

Where data is your array of objects.

I hope I'm clear :/

Answer

As an alternative to multiselect('dataprovider', data) you can build the list with jquery append exactly the way you did in your question. The only change you need to make is to delay the rebuild until after the ajax request is complete.

var buildDrivers = $.getJSON('resources/orders/drivers.json', function(data) { 
   $.each(data, function(i, driver) {
      $('#toolbar select[name="drivers"]').append('<option>'+driver+'</option>');
   });
});
buildDrivers.complete(function() {
    $('.multiselect').multiselect('rebuild');
});

see http://api.jquery.com/jquery.getjson/ for documentation

Answer

I've been added the functionality of updating options after filtering and getting them from the server side. This solution relays on the concept of injecting new options, destroying the select and initializing it again.

I took into account:

  1. Considering the existing selected options, which must stay.
  2. Removing duplicate options (might be as a conflict from which that already selected and the new that came from the server).
  3. Keeping the options tray open after the update.
  4. Reassign the previous text in the search text box & focusing it.

Just add the 'updateOptions' as a function after the 'refresh' function along with the two helper functions as follows:

updateOptions: function (options) {
        var select = this.$select;
        options += this.getSelectedOptionsString();
        var selectedIds = select.val(),
            btnGroup = select.next('.btn-group'),
            searchInput = btnGroup.find('.multiselect-search'),
            inputVal = searchInput.val();

        options = this.removeOptionsDuplications(options);
        if (!options) {
            options = '<option disabled></option>';
        }

        // 1) Replacing the options with new & already selected options
        select.html(options);

        // 2) Destroyng the select
        select.multiselect('destroy');

        // 3) Reselecting the previously selected values
        if (selectedIds) {
            select.val(selectedIds);
        }

        // 4) Initialize the select again after destroying it
        select.multiselect(this.options);

        btnGroup = select.next('.btn-group');
        searchInput = btnGroup.find('.multiselect-search');

        // 5) Keep the tray options open
        btnGroup.addClass('open');

        // 6) Setting the search input again & focusing it
        searchInput.val(inputVal);
        searchInput.focus();
    },
    getSelectedOptionsString: function () { // Helper
        var result = '',
            select = this.$select,
            options = select.find('option:selected');

        if (options && options.length) {
            $.each(options, function (index, value) {
                if (value) {
                    result += value.outerHTML;
                }
            });
        }

        return result;
    },
    removeOptionsDuplications: function (options) { // Helper
        var result = '',
            ids = new Object();

        if (options && options.length) {
            options = $(options);
            $.each(options, function (index, value) {
                var option = $(value),
                    optionId = option.attr('value');

                if (optionId) {
                    if (!ids[optionId]) {
                        result += option[0].outerHTML;
                        ids[optionId] = true;
                    }
                }
            });
        }
        return result;
    },

Demo:

State:

"Option 1"

$('#select').multiselect('updateOptions', '<option value="2">Option 2</option>');

State:

"Option 2"

"Option 1"

Answer

I think this is an easier way to add options on the fly (using ajax or any other listener) to an existing Bootstrap MultiSelect.

Following is a simplified example to add options:

function addOptionToMultiSelect(multiselectSelector, value, selected) {
    var data = [];
    $(multiselectSelector + ' option').each(function(){
        var value = $(this)[0].value;
        var selected = $(this)[0].selected;
        data.push({label: value, value: value, selected: selected});
    });

    // Add the new item
    data.push({label: value, value: value, selected: selected});

    $(multiselectSelector).multiselect('dataprovider', data);
}

For simplicity, I have assumed both the label and value are the same in an option. Note that the already selected options are taken care of by reading the selected attribute from the existing options. You can make it more sophisticated by tracking the disabled and other attributes.

Sample:

addOptionToMultiSelect('#multiselect-example', 'new-option', true);

Tags

Recent Questions

Top Questions

Home Tags Terms of Service Privacy Policy DMCA Contact Us

©2020 All rights reserved.