I have 2 multi-select boxes like this
<div class="form-group mb-3"> <p class="mb-1 font-weight-bold text-muted mt-3 mt-md-0">Addons</p> <p class="text-muted font-13">Select multiple Addons</p> <select class="form-control select2-multiple" id="multi-select-add-ons" data-toggle="select2" multiple="multiple" data-placeholder="Choose ..." style="width: 100%;"> <optgroup label="Select addons.."> @foreach ($addons as $a) <option value="{{$a->id}}">{{ $a->name }}</option> @endforeach </optgroup> </select> <div class="form-group"> <input id="resultAddons" type="hidden" name="addons_id"> </div> </div> <div class="form-group mb-3"> <label for="simpleinput">SubAddons</label> <select name="" id="subAddons" class="form-control select2-multiple" data-toggle="select2" multiple="multiple" data-placeholder="Choose ..." style="width: 100%;"> <optgroup label="Select subaddons.."> <option value="0"></option> </optgroup> </select> <div class="form-group"> <input id="resultSubAddons" type="hidden" name="sub_addons_id"> </div> </div>
Ok so I am using the following code in Script section to get data from Api
<script> $('select').change(function () { var addons = $("#multi-select-add-ons").val(); //console.log(addons); $('#subAddons').find('option').not(':first').remove(); addons.map(item => getSubAddonsByAddon(item)) //call subaddons by addon id api addons = addons.join(", "); document.getElementById('resultAddons').value = addons; }); function getSubAddonsByAddon(id) { let baseUrl = 'http://localhost.test/add-ons/' var xhr = new XMLHttpRequest(); xhr.open("GET", `${baseUrl}show/${id}/sub-add-ons`, true); xhr.setRequestHeader("Content-Type", "application/json"); xhr.onreadystatechange = function() { // Call a function when the state changes. if (this.readyState === XMLHttpRequest.DONE && this.status === 200) { let data = JSON.parse(this.response); let complexArr = [data][0].data; complexArr.forEach(element => { // console.log(element.name); getSubAddonIdAndName(element); }); } } xhr.send(); } let subAddonID, name; function getSubAddonIdAndName(data) { this.subAddonID = data.id; this.name = data.name; $("#subAddons").append($('<option>', { value: data.id , text: data.name })); } </script>
Here’s how it looks, the code works fine, the 2nd select (sub-addons) dropdown is updated as per the selection of addons, how the name is not displayed inside the select box text field
After selecting a value from 2nd select box, the value is not displayed like the first select box value’s
It goes back to “Choose…” instead of displaying name like first box
Answers:
Thank you for visiting the Q&A section on Magenaut. Please note that all the answers may not help you solve the issue immediately. So please treat them as advisements. If you found the post helpful (or not), leave a comment & I’ll get back to you as soon as possible.
Method 1
To show option inside select-box textfield you can add selected: true
line when you append new option inside your select2
and then $("#subAddons").trigger("change")
to update your select2 plugin .
Then , your second issue is because of $('select').change(function () {
line as you have use select
as selector so when you change option inside your second select-box this event gets called and option are getting again updated . So , to avoid this just use more specific selector i.e : select#multi-select-add-ons
Demo Code :
$("#multi-select-add-ons ,#subAddons").select2()
//be more specific here
$('select#multi-select-add-ons').change(function() {
var addons = $("#multi-select-add-ons").val();
$('#subAddons').find('option:not(:first)').remove();
addons.map(item => getSubAddonsByAddon(item))
addons = addons.join(", ");
document.getElementById('resultAddons').value = addons;
});
function getSubAddonsByAddon(id) {
/*let baseUrl = 'http://localhost.test/add-ons/'
var xhr = new XMLHttpRequest();
xhr.open("GET", `${baseUrl}show/${id}/sub-add-ons`, true);
xhr.setRequestHeader("Content-Type", "application/json");
xhr.onreadystatechange = function() { // Call a function when the state changes.
if (this.readyState === XMLHttpRequest.DONE && this.status === 200) {
let data = JSON.parse(this.response);*/
//suppose this is data came from server
let data = [{
"data": [{
"id": 1,
"name": "abc"
}, {
"id": 2,
"name": "ace"
}]
}]
let complexArr = data[0].data;
complexArr.forEach(element => {
getSubAddonIdAndName(element);
});
$("#subAddons").trigger("change") //after appending options refresh select2
/*}
}
xhr.send();*/
}
let subAddonID, name;
function getSubAddonIdAndName(data) {
this.subAddonID = data.id;
this.name = data.name;
$("#subAddons").append($('<option>', {
value: data.id,
text: data.name,
selected: true //add this
}));
}
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/select2/4.0.0/css/select2.min.css" rel="nofollow noreferrer noopener" />
<script src="https://code.jquery.com/jquery-3.2.1.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/select2/4.0.0/js/select2.full.min.js"></script>
<div class="form-group mb-3">
<p class="mb-1 font-weight-bold text-muted mt-3 mt-md-0">Addons</p>
<p class="text-muted font-13">Select multiple Addons</p>
<select class="form-control select2-multiple" id="multi-select-add-ons" data-toggle="select2" multiple="multiple" data-placeholder="Choose ..." style="width: 100%;">
<optgroup label="Select addons..">
<option value="1">A</option>
<option value="2">A2</option>
<option value="3">A3</option>
</optgroup>
</select>
<div class="form-group">
<input id="resultAddons" type="hidden" name="addons_id">
</div>
</div>
<div class="form-group mb-3">
<label for="simpleinput">SubAddons</label>
<select name="" id="subAddons" class="form-control select2-multiple" data-toggle="select2" multiple="multiple" data-placeholder="Choose ..." style="width: 100%;">
<optgroup label="Select subaddons..">
<option value="0"></option>
</optgroup>
</select>
<div class="form-group">
<input id="resultSubAddons" type="hidden" name="sub_addons_id">
</div>
</div>
Method 2
if you are using a library for the multiple select, what happens is the library runs a handling method on your inputs for whatever data it has for the first time, if you append more data to it you need to re-call the handle method of that library.
All methods was sourced from stackoverflow.com or stackexchange.com, is licensed under cc by-sa 2.5, cc by-sa 3.0 and cc by-sa 4.0