2
\$\begingroup\$

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);
 });
});

jsfiddle

Jamal
35.2k13 gold badges134 silver badges238 bronze badges
asked Sep 24, 2014 at 20:05
\$\endgroup\$

1 Answer 1

2
\$\begingroup\$
  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).

  2. Be consistent with your naming; Sublist is capitalized, but choices is lowercase.

  3. 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);
});

Here's a demo

answered Sep 24, 2014 at 21:02
\$\endgroup\$

Your Answer

Draft saved
Draft discarded

Sign up or log in

Sign up using Google
Sign up using Email and Password

Post as a guest

Required, but never shown

Post as a guest

Required, but never shown

By clicking "Post Your Answer", you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.