Topic: Calling setValue() on a Select with a preselected option sometimes retains the preselected option as label
Expected behavior
I have a select with one of the options having selected="true" enabled, and two links that attempts to select another value.
Both of these are in a snippet at the bottom. I expect clicking the "setToFirstValue" linkto update the label to "All" and the "setToLastValue" link to update the label to "Five".
Actual behavior
While the setToLastValue link does in fact set the fake-label of the select to Five, the setToFirstValue link doesn't do this and in fact sets it to the option that has the selected attribute.
I've dug deep into the MDB Select code, and I have found this is because when MDB unsets the selected attribute, it sets the nativeOption selected attribute to false, but the attribute still remains on the option object.
Later, MDB converts the option tags of the Select back to PlainOption objects, and to determine the selected attribute of these objects, it does a = t.selected || t.hasAttribute("selected"). t.selected evaluates to false, but then it does t.hasAttribute("selected"), which evaluates to true since there's a selected="false" attribute on the tag.
This leads to at least 2 options have "selected=true" enabled with regards to what label needs to be shown. Since MDB loops over all options, even in case of a single select, it uses the last of the selected options.
Resources (screenshots, code snippets etc.)
<select data-mdb-select-init id="selectID">
<option value="-1">All</option>
<option value="2" selected="selected">Two</option>
<option value="3">Three</option>
<option value="4">Four</option>
<option value="5">Five</option>
</select>
<label class="form-label select-label">Example label</label>
<a href="" onclick="return false;" id="setToFirstValue" class="icon-link">set me To "-1"</a>
<a href="" onclick="return false;" id="setToLastValue" class="icon-link">set me To "5"</a>
I have the following Javascript code to do this:
document.querySelector("#setToFirstValue").addEventListener('click', () => {
let select = document.getElementById("selectID");
mdb.Select.getOrCreateInstance(select).setValue("-1");
});
document.querySelector("#setToLastValue").addEventListener('click', () => {
let select = document.getElementById("selectID");
mdb.Select.getOrCreateInstance(select).setValue("5");
});
snippet:
https://mdbootstrap.com/snippets/standard/ikan_nak/6193216#js-tab-view
Kamila Pieńkowska staff answered 5 months ago
We suggest setting preselected options with setValue
method not with attribute:
https://mdbootstrap.com/snippets/standard/kpienkowska/6194622
ikan_nak pro premium priority commented 5 months ago
Thanks for this information. I use a Struts 6 select tag as the base for the select because it allows me to more easily generate the option compared to doing it manually using an iterator tag, and the default Struts 6 select template automatically sets the "selected" attribute on any options that match the value attribute of the select.
Since we only use setValue when resetting the select to a predetermined default value that's different from the currently selected value, we decided to adjust our code to work around this design choice by resetting the selected attribute on the nativeOption and internal mdb select options before selecting the default value:
let select = document.getElementById(selectId);
select.querySelectorAll("option").forEach((option) => { option.hasAttribute("selected") && option.removeAttribute("selected"); });
let mdbSelect = mdb.Select.getOrCreateInstance(select);
mdbSelect.options.filter((option) => {option.selected;}).forEach((option) => {option.selected = false;});
FREE CONSULTATION
Hire our experts to build a dedicated project. We'll analyze your business requirements, for free.
Answered
- User: Pro
- Premium support: Yes
- Technology: MDB Standard
- MDB Version: MDB5 7.3.0
- Device: Desktop computer
- Browser: Edge
- OS: Windows 11
- Provided sample code: No
- Provided link: Yes