On selection from drop-down A (HTML select
) I need to populate another "sub"-dropdown with a different list of values. For instance, on selection of country in dropdown A, dropdown B should be filled with the list of cities of selected country.
This is my first attempt of writing such a thing in jQuery. Please point out areas for improvement, like more idiomatic or shorter way of achieving this result (without losing much readability if possible).
HTML:
<select id="Parentlist">
</select>
<select id="Sublist">
</select>
<table id="choices">
<tr id="Poland" style="display:none">
<td id="Krakow"></td>
<td id="Warszawa"></td>
</tr>
<tr id="Germany" style="display:none">
<td id="Frankfurt"></td>
<td id="Berlin"></td>
</tr>
</table>
JavaScript + jQuery:
function populateParentlist(choice) {
$('#choices').find('tr').each(function() {
trowid = $(this).attr('id');
$("#Parentlist").append('<option>' +trowid + '</option>');
});
}
function populateSublist(choice) {
$('#Sublist').find('option').remove();
$('#choices').find('tr').each(function() {
trowid = $(this).attr('id');
$(this).find('td').each(function() {
tdid = $(this).attr('id');
if(trowid != choice)
return;
$('#Sublist').append('<option>' + tdid + '</option>');
});
});
}
populateParentlist('Poland')
populateSublist('Poland')
$(function() {
$("#Parentlist").change(function() {
var parsel = $(this).val();
populateSublist(parsel);
});
});
1 Answer 1
Don't use a
<table>
element to "hide" extra data in your markup. It's a terribly complex way of doing things, and it's pretty hacky to have large, hidden elements like that (and not a good semantic use of a table either).Be consistent with your naming;
Sublist
is capitalized, butchoices
is lowercase.Alphabetize the city names :)
With regard the JS: It's ok given the context, but the use of the table is the real culprit. Still there's at least 1 thing you should change:
Don't call the populate*
before the page has loaded (you wait before adding the change
handler, because the #ParentList
element might not have loaded yet; that same timing issue would cause the populateParentlist
function to fail)
Now, ideally, the city list should be available as JSON or something (loaded from the server for instance), but if you're going to store it in the HTML, you might as well use a select
and subdivide it using optgroup
elements:
<select id="cities">
<optgroup label="Poland">
<option selected>Krakow</option>
<option>Warszawa</option>
</optgroup>
...
As a bonus, the list will work even without javascript. And you can set the initially-selected city in the HTML.
It also contains all the option elements you'll need for the city dropdown; we just need to convert the optgroups into options for a 2nd dropdown:
$(function () { // wait for page to load
var cityDropdown = $("#cities"),
countryDropdown = $('<select></select>'), // create a country dropdown
countries = []; // ordered list of countries
// parse the nested dropdown
cityDropdown.children().each(function () {
var group = $(this),
countryName = group.attr('label'),
option;
// create an option for the country
option = $('<option></option>').text(countryName);
// store the associated city options
option.data('cities', group.children());
// check if the country should be selected
if( group.find(':selected').length > 0 ) {
option.prop('selected', true);
}
// add the country to the dropdown
countryDropdown.append(option);
});
// add the country dropdown to the page
cityDropdown.before(countryDropdown);
// this function updates the city dropdown based on the selected country
function updateCities() {
var country = countryDropdown.find(':selected');
cityDropdown.empty().append(country.data('cities'));
}
// call the function to set the initial cities
updateCities();
// and add the change handler
countryDropdown.on('change', updateCities);
});
Explore related questions
See similar questions with these tags.