Reputation: 13
I've been using JQuery to populate a drop down list on the click of a HTML select element. The options get created however on the first click the options get shown in a very small box with a scroll. see below
If I then close and reopen the dropdown it appears correctly. as below.
It feels like the dropdown list is appearing before jquery has rendered the new options elements. I've tried to find away to re-render it but with no luck.
This feels like it should be such an easy fix but I'm new to scripting and struggling.
HTML
<select class="custom-select" id="templateGroupName" name="templateGroupName">
<option selected>Please Select a group</option>
</select>
JS - Wrapped in document.ready
$('#templateGroupName').click(function () {
$.ajax({
type: "GET",
url: '/Layout/GetGroups',
success: function (data) {
helpers.buildDropdown(
data,
$('#templateGroupName'),
'Select an option'
);
}
});
});
var helpers =
{
buildDropdown: function (result, dropdown, emptyMessage) {
// Remove current options
dropdown.html('');
// Add the empty option with the empty message
dropdown.append('<option value="">' + emptyMessage + '</option>');
// Check result isnt empty
if (result != '') {
// Loop through each of the results and append the option to the dropdown
$.each(result, function (k, v) {
dropdown.append('<option value="' + v.Id + '">' + v.Name + '</option>');
});
}
}
}
Upvotes: 0
Views: 1001
Reputation: 520
The browser gets confused when you inject options while the <select>
is open. To be fair, your users would probably be confused too.
If you're waiting for something to load, tell them to wait. If something isn't usable, disable it.
Putting these two together: the first time a user hovers over the <select>
, disable it and set the cursor to a loading wheel. Wait until your data loads, then insert the options, re-enable it and switch the cursor back.
var helpers = {
buildDropdown: function(result, dropdown, emptyMessage) {
dropdown.html('');
dropdown.append(`<option value="">${emptyMessage}</option>`);
if (!!result) {
$.each(result, function(k, v) {
dropdown.append(`
<option value="${v.Id}">
${v.Name}
</option>
`);
});
}
}
}
const $DROPDOWN = $('#templateGroupName');
// using jQuery#one to only fire the click event once
$DROPDOWN.one('mouseenter', _ => {
// disable dropdown while loading options
$DROPDOWN.attr('disabled', true)
console.log('loading options...');
// replace contents with your GET request
setTimeout(function() {
helpers.buildDropdown(
Array.from({
length: 30
}, (_, i) => ({
Id: i,
Name: i
})),
$DROPDOWN,
'Select an option'
);
// un-disable after options are loaded and inserted
$DROPDOWN.attr('disabled', false)
}, 1000);
})
/* Show "loading" wheel while loading */
select.custom-select[disabled] {
cursor: wait;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<select class="custom-select" id="templateGroupName" name="templateGroupName">
<option selected>Please Select a group</option>
</select>
Upvotes: 0
Reputation: 114367
First, you need a <select>
as the parent, not an empty element,
dropdown = $('#templateGroupName');
then insert it as a document element, not a string:
var opt = document.createElement('option');
opt.value = v.Id;
opt.innerHTML = v.Name;
dropdown.appendChild(opt);
Upvotes: 1