Cascading Select Menus

Contact Us or call 1-877-932-8228
Cascading Select Menus

Cascading Select Menus

Cascading select menus allow you to populate one select menu based on a choice made in another select menu. For example, a menu of states might change based on the country that was selected in another menu, as shown in the following example:

Code Sample:

DynamicForms/Demos/cascading.html
<!DOCTYPE HTML>
<html>
<head>
<meta charset="UTF-8">
<title>Cascading Dropdowns</title>
<script type="text/javascript" src="../../lib.js"></script>
<script type="text/javascript">
	var statesPerCountry = {
		"usa" : ["New York", "Florida", "Iowa", "California"],
		"canada" : ["Ontario", "Quebec", "Manitoba", "Yukon"]
	};
	
	function countryChanged() {
		var sel = document.getElementById("country");
		var country = sel.options[sel.selectedIndex].value;
		updateStateList(country);
	}
	
	function updateStateList(country) {
		var states = statesPerCountry[ country ];
		var list = document.getElementById("state");
		var opt;
		removeAllChildren(list);
		for (var i in states) {
			opt = new Option(states[i]);
			appendOptionToSelect(list,opt);
		}
	}
	
	observeEvent(window,"load",function() {
		var country = document.getElementById("country");
		observeEvent(country,"change",countryChanged);
	});
</script>
</head>
<body>
	<h1>Cascading Dropdowns</h1>
	<form action="">
		<label for="country">Country:</label>
		<select id="country" name="country">
			<option value="">Please select</option>
			<option value="usa">USA</option>
			<option value="canada">Canada</option>
		</select>
		<label for="state">State/Province:</label>
		<select id="state"></select>
	</form>
</body>
</html>

Let's look at the code above in detail.

  1. As the page loads, we create a statesPerCountry object that contains two properties: usa and canada, each of which holds an array of states (provinces).
  2. The body of the page contains a form with two select menus: country and state
  3. In the JavaScript, we call the countryChanged() function when a change event occurs on country select.
  4. The countryChanged() function determines the name of the country selected and passes it into the updateStateList() function, which removes all elements from the state select list: removeAllChildren(list); and then adds new options getting the values by looping through the array associated with the passed-in country.

Making the Code Modular

A problem with the code in DynamicForms/Demos/cascading.html is that it would need to be modified in several places to add or change options. This next example, though more complex, is much more modular, and hence, reusable.

Code Sample:

DynamicForms/Demos/cascading-refactored.html
---- C O D E   O M I T T E D ----

<script type="text/javascript">
	function selChanged(sel,data,dependentSel) {
		var selection = sel.options[sel.selectedIndex].value;
		var arrOptions = data[selection];
		var opt;
		removeAllChildren(dependentSel);
		for (var i in arrOptions) {
			opt = new Option(arrOptions[i]);
			appendOptionToSelect(dependentSel,opt);
		}
	}
	
	observeEvent(window,"load",function() {
		var statesPerCountry = {
			"usa" : ["New York", "Florida", "Iowa", "California"],
			"canada" : ["Ontario", "Quebec", "Manitoba", "Yukon"]
		};
		var country = document.getElementById("country");
		var state = document.getElementById("state");
		observeEvent(country,"change",function() {
			selChanged(country,statesPerCountry,state);
		});
		
		var employeesPerCompany = {
			"Webucator" : ['Nat', 'Connie', 'Brian', 'Steve'],
			"Microsoft" : ['Bill', 'Paul', 'Steve']
		};
		var company = document.getElementById("company");
		var employee = document.getElementById("employee");
		observeEvent(company,"change",function() {
			selChanged(company,employeesPerCompany,employee);
		});
	});
</script>
</head>
<body>
	<h1>Cascading Dropdowns</h1>
	<form action="">
		<label for="country">Country:</label>
		<select id="country" name="country">
			<option value="">Please select</option>
			<option value="usa">USA</option>
			<option value="canada">Canada</option>
		</select>
		<label for="state">State:</label>
		<select id="state"></select>
		<hr>
		<label for="company">Company:</label>
		<select id="company" name="company">
			<option value="">Please select</option>
			<option value="Webucator">Webucator</option>
			<option value="Microsoft">Microsoft</option>
		</select>
		<label for="employee">Employee:</label>
		<select id="employee"></select>
	</form>
</body>
</html>

Now we have two different objects: statesPerCountry and employeesPerCompany, each of which holds a couple of arrays to populate the cascading select menus. We observe change events on both the country and company select menus. When they change, we call the selChanged() function passing in the select menu itself, the relevant object with its arrays, and the dependent select menu.

The selChanged() function gets the value of the option selected in the main list, uses that to select the appropriate array from the passed-in object of arrays, and uses that array to populate the dependent select list.

Again, the nice thing about this code is we can reuse it for other cascading (or interdependent) select lists.

Next