Open VeloAddict opened 2 years ago
I suspect the bug has something to do with the $('.selectpicker').selectpicker('refresh');
command.
I can confirm that the .selectpicker('refresh') call creates a newly refreshed list but doesn't remove the old one.
Commit 04cc1fd5abedc85c449d159d9fa6ea48e2e4a2f7 introduces the bug, but I didn't found why yet.
I believe the problem resides on the buildData
method.
On version beta2 the following did not produce the duplication bug (lines 1776-1790):
switch (type) {
case 'data': {
this.selectpicker.main.data = this.selectpicker.current.data = mainData;
break;
}
case 'load': {
Array.prototype.push.apply(this.selectpicker.main.data, mainData);
this.selectpicker.current.data = this.selectpicker.main.data;
break;
}
case 'search': {
Array.prototype.push.apply(this.selectpicker.search.data, mainData);
break;
}
}
But now on the current version beta3 the following is producing the duplication (lines 1805-1818):
switch (type) {
case 'data': {
if (!this.selectpicker.main.data) {
this.selectpicker.main.data = [];
}
> Array.prototype.push.apply(this.selectpicker.main.data, mainData);
> this.selectpicker.current.data = this.selectpicker.main.data;
break;
}
case 'search': {
Array.prototype.push.apply(this.selectpicker.search.data, mainData);
break;
}
}
From what I could gather, the line 1810 (signaled with >
), where mainData
is being pushed
to selectpicker.main.data
is where the duplication occurs (since selectpicker.main.data
already has the items, and that line is pushing
the items into the array again)
The following fixes the duplication, but not the selection, neither the text displayed
Commenting that line and adding = mainData
at the end of the next line seems to solve the duplication issue - basically reverting these 2 lines to the previous beta version. As follows:
switch (type) {
case 'data': {
if (!this.selectpicker.main.data) {
this.selectpicker.main.data = [];
}
> //Array.prototype.push.apply(this.selectpicker.main.data, mainData);
> this.selectpicker.current.data = this.selectpicker.main.data = mainData;
break;
}
case 'search': {
Array.prototype.push.apply(this.selectpicker.search.data, mainData);
break;
}
}
@yankarinRG commented on #2724: I am also using the workaround of calling selectpicker('destroy') and then selectpicker(), in the meantime of an official bug fix from the author. It's certainly not the most elegant and probably also optimized solution, but at least it works!
Works for this issue too, thanks.
Can we get a beta release to include this fix?
An easy workaround is to destroy and recreate selectpicker, after select modifications:
let select = $('select#foo');
select.find('option').remove(); // remove all options
select.append($('<option/>', {
value: 52,
text : "new item in empty list",
}));
select.selectpicker('destroy'); // temporary patch!
select.selectpicker(); // temporary patch!
I needed the $(ele).selectpicker('refresh') to work now without much rewrite of code.
A dirty, but quick fix is to add this into the refresh: function() {} of the source code.
$(this.$element[0]).selectpicker('destroy');
$(this.$element[0]).selectpicker();
return;
I changed it using these codes
$('.selectpicker').selectpicker('destroy');
$('.selectpicker').val('').selectpicker('update');
I could fix the duplicated displayed text with the following change:
On line 317 I changed the if statement
if (this.options.source.data && !this.multiple && selectedOptions.length > 1) {
with
if (!this.multiple && selectedOptions.length > 1) {
this.options.source.data was always empty and so the conditions was never true.
I'm still testing but it seems to work.
Thanks for the patch!
Where i can find the NPM version with this bug fixed? 1.14.0-beta3 still have this bug, i have reverted to 1.14.0-beta2
My solution to the problem is not one of the best in the world, but it did.
$.each(my_list, function (index, value) {
$(`#my-select-id`).append('<option value="' + value.token + '">' + value.text + "</option>");
})
$.each(my_list, function (index, value) {
if ($(`#my-select-id option[value='${value.token}']`).text().length == 0) {
$(`#my-select-id`).append('<option value="' + value.token + '">' + value.text + "</option>");
}
});
Although @MiguelMRebocho solve the duplicated option issue, the prevData
deselection still not working, bc prevOption.liIndex
value is nowhere to that.selectpicker.main.data
range. (Same to prevIndex
suggested by @jayb611 in 2712).
prevData = prevOption ? that.selectpicker.main.data[prevOption.liIndex] : false,
that.selectpicker.main.data
is a filtered dataset, without disabled options.
How can I pair prevOption ( equal to that.$element[0].options[selectedIndex]
) to that?
In this picture: it is the 4th, option.op_inprogress
, liIndex
is 7, but on main.data it should be 1.
So my solution: skip that prevData search, deselect everything, before new select. Edit line 2794:
//if (prevData) that.setSelected(prevData, false);
that.deselectAll(); //insert this
that.setSelected(clickedData, true);
Disable multi check in line 3634:
//if (!this.multiple) return;
An easy workaround is to destroy and recreate selectpicker, after select modifications:
let select = $('select#foo'); select.find('option').remove(); // remove all options select.append($('<option/>', { value: 52, text : "new item in empty list", })); select.selectpicker('destroy'); // temporary patch! select.selectpicker(); // temporary patch!
BE AWARE that this also destroys any event bindings on the picker so after re-initializing it you'd have to set them again. So that was not satisfactory for me and looked into the code to try a better fix...
THIS IS WHAT SEEMS TO WORK for both preventing the item as well as selection duplication:
In the "refresh" function I added
this.selectpicker.main.data = null;
after the "else" in the first conditional statement like so:
if (this.options.source.data) {
this.render();
this.buildList();
} else {
this.selectpicker.main.data = null; // Marek Vsechovsky's fix: Fixes https://github.com/snapappointments/bootstrap-select/issues/2738 (duplication of list items and selections on "refresh").
this.fetchData(function () {
that.render();
that.buildList();
});
}
hi there! I'm working with cascade select, with countries, states and cities like this.
// document ready with options do you want ( all selects)
$('.selectpicker').selectpicker({
//liveSearch: true,
liveSearchNormalize: true,
dropupAuto: true,
size: 6,
});
Then on change :
$("#selectPaises").on("change", function (e) {
var pais = this.value;
LoadProvincias(pais);
});
function LoadProvincias(pais) {
var select = $("#selectProvincias");
if (pais > 0) {
$.getJSON('?handler=Provincias&pais=' + pais + '', (data) => {
// clear options
select.find("option").remove();
// add new options
$.each(data, function (i, item) {
select.append("<option data-tokens='" + item.provinciaKey + "' value='" + item.provinciaId + "'>" + item.provinciaNombre + "</option>");
});
// clear + refresh
select.selectpicker("destroy");
select.selectpicker("render");
});
}
else {
}
}
I call to "render" method because select.selectpicker();
lost the preferences . destroy + refrsh dosn't work.
For me, the quickest fix is to destroy and reinit the selectpicker:
$(selector).selectpicker('destroy');
$(selector).selectpicker();
Anyway any chance to fix the issue?
For me, the quickest fix is to destroy and reinit the selectpicker:
$(selector).selectpicker('destroy'); $(selector).selectpicker();
Anyway any chance to fix the issue?
@czachor Is it working? I did the same, but it is removing select
element altogether.
@aliml92 Yes. Just define selector
earlier, eg. let selector = $('#theSelector');
.
Thank you @czachor. It worked. However when pressing the back button, the select button is becoming unresponsive.
let certSelect = $("#cert-select")
certSelect.append($("<option>").attr("data-tokens", "auto").val("auto").text(`AUTO`));
certSelect.selectpicker()
still not work for me ?
FYI, this was fixed in this PR: https://github.com/snapappointments/bootstrap-select/pull/2816
Since there's no release, we downloaded the non minified latest version from the dev branch and it works: https://github.com/snapappointments/bootstrap-select/blob/dev/js/bootstrap-select.js
да, действительно если
case 'data': {
if (!this.selectpicker.main.data) {
this.selectpicker.main.data = [];
}
Array.prototype.push.apply(this.selectpicker.main.data, mainData);
this.selectpicker.current.data = this.selectpicker.main.data;
break;
},
заменить на
case 'data': {
this.selectpicker.main.data = this.selectpicker.current.data = mainData;
break;
}
case 'load': {
Array.prototype.push.apply(this.selectpicker.main.data, mainData);
this.selectpicker.current.data = this.selectpicker.main.data;
break;
}
то проблема с refresh решается
This bug appeared with 1.14.0-beta3.