truckingsim / Ajax-Bootstrap-Select

This uses the bootstrap-select plugin and extends it so that you can use a remote source to search.
MIT License
280 stars 97 forks source link

Setting the selected value initially and doing a search, shows empty "currently selected" #177

Open ppazos opened 5 years ago

ppazos commented 5 years ago

I have set the selected value on the select picker:

$('#myselect').selectpicker('val', '1');

I can see the correct option selected by default (though in the DOM the correspondent select option doesn't have the selected attribute).

Then I click on the select and to a search via AJAX, and the result says "Currently selected" showing no value, even though I didn't click on any result so I expect "Currently selected" to be the one initially set.

markhalliwell commented 4 years ago

This sounds like a legit bug. Will have to look into it more at some point.

Humni commented 4 years ago

I'm also affected by this - it also means you can't recycle the select picker when toggling an "edit" mode in a UI (i.e. clicking "edit" on a page which displays the editing fields dynamically).

If you don't need to recycle the select picker, you can set a default value like this:

seeAlsoSelect.append('<option value="' + item + '" selected="selected">' + item + '</option>');
Humni commented 4 years ago

@ppazos I've got a complete workaround for this now. For updating the selected values manually, you can use the following code

let mySelect = $('#myselect');
mySelect.selectpicker('val', '1');
ajaxPickerValueFix(mySelect);

function ajaxPickerValueFix(picker){
            var internals = picker.data('AjaxBootstrapSelect');
            var selected = [];
            var template = {
                value: "value",
                text: "value",
                class: "",
                data: {},
                preserved: true,
                selected: true
            };
            var selectValues = internals.selectpicker.val();
            for(var index in selectValues){
                var structure = Object.assign({}, template);
                structure.value = selectValues[index];
                structure.text = selectValues[index];
                selected.push(structure);
            }
            internals.list.selected = selected;
}
quaternion7 commented 4 years ago

Based on @Humni 's response, I tweaked it and made it into a jQuery function:

$.fn.ajaxSelectPickerRefresh = function(){
    return this.each(function () {
        if(!$(this).data('AjaxBootstrapSelect')) return;
        var picker = $(this).data('AjaxBootstrapSelect');
        var selected = [];
        var selectValues = picker.$element.find('option:selected');
        for(var i=0;i<selectValues.length;i++){
            selected.push({
                value: selectValues[i].value,
                text: selectValues[i].text,
                class: "",
                data: {},
                preserved: true,
                selected: true
            });
        }
        picker.list.selected = selected;
    });
}

Then it can be used as such: $('#myselect').append(html_options).selectpicker('refresh').ajaxSelectPickerRefresh(); Or in the OP's case: $('#myselect').selectpicker('val', '1').ajaxSelectPickerRefresh();

ppazos commented 4 years ago

@quaternion7 should that be a PR to solve the issue?

calumshep commented 4 years ago

@quaternion7 I've used that function and it's solved my issue, but the <select>'s placeholder still shows "Start typing to search..." instead of the selected values. Any ideas?

demetris-manikas commented 4 years ago

@calumshep I found that calling picker.list.replaceOptions(selected); after picker.list.selected = selected;

did solve my problem.

calumshep commented 4 years ago

Can confirm that @demetris-manikas addition to @quaternion7's solution fixes this! Final solution:

$.fn.ajaxSelectPickerRefresh = function(){
    return this.each(function () {
        if(!$(this).data('AjaxBootstrapSelect')) return;
        var picker = $(this).data('AjaxBootstrapSelect');
        var selected = [];
        var selectValues = picker.$element.find('option:selected');
        for(var i=0;i<selectValues.length;i++){
            selected.push({
                value: selectValues[i].value,
                text: selectValues[i].text,
                class: "",
                data: {},
                preserved: true,
                selected: true
            });
        }
        picker.list.selected = selected;
       picker.list.replaceOptions(selected);
    });
}
outaTiME commented 3 years ago

thanks @calumshep, i made some adjustements to your code:

$.fn.ajaxSelectPickerRefresh = function () {
  return this.each(function () {
    var picker = $(this).data('AjaxBootstrapSelect');
    if (!picker) {
      return;
    }
    var selected = [];
    var selectValues = picker.$element.find('option:selected');
    for (var i = 0; i < selectValues.length; i++) {
      selected.push({
        value: selectValues[i].value,
        text: selectValues[i].text,
        'class': '',
        data: {},
        preserved: picker.options.preserveSelected,
        selected: true
      });
    }
    picker.list.selected = selected;
    picker.list.replaceOptions(selected);
    // clear status text
    picker.list.setStatus();
  });
};