Populating Multiple Drop-downs Dynamically

Food Group Select MenusFirst off I want to say that there are multiple ways of doing something like this. Below is two ways (and I mention a third) to dynamically populate one drop down using the selection of another drop down (aka chaining drop-downs). One way we will see uses a pure JavaScript implementation and another is using a combination of JavaScript and a server-side language (here we are demonstrating PHP). After we get done talking about these two methods, I will briefly mention the third less savvy way.

For our demonstration purposes I am going to use two simple selects. One which we will call “Food Groups” and another which we labeled as “Food”. When the user selects a food group we want the foods drop down to clear its contents and then list the foods that are related to that specific food group.

<!-- Our food group drop down-->
<select id="foodgroups">
	<option value="">Select a Food Group</option>
	<option value="1">Fruit</option>
	<option value="2">Vegetables</option>
	<option value="3">Meat</option>
	<option value="4">Dairy</option>
	<option value="5">Grains</option>
</select>

<!-- Our foods for a group selection (empty on default) -->
<select id="foods"></select>

Pure JavaScript Implementation

The pure JavaScript implementation is easy to do for simple and SMALL lists. What we want is to simply create a jagged array (an array of arrays of varying lengths) and then simply reference them using the option value from the food groups drop down. Notice the values for our food group drop down. Here we set them up using a simple index value for demonstration purposes. You could also use this trick (with modification) to create keys that you then use to access the individual arrays. I figure this limited use would be great to keep the code rather simple and straight forward.

To make the pure implementation work we will need to add an event handler to the food groups select box. When the option changes we will call our function to populate the second list box. So alter the code above with this line…

<select id="foodgroups" onchange="selectFoods(this.options[this.selectedIndex].value)">

Here we are simply saying “Call selectFoods and pass it the selected option’s value.”. So if we select “Grains” the value 5 will be passed to our function. The JavaScript for this is listed below. We will take the selected index value, subtract 1 from it (since our array starts at 0), check to make sure it is in the range of valid indexes and then use it to access the particular array. Once we have done that it is just a matter of looping through the array elements of that group. We clear the existing options by setting the length of the options array to zero and then adding each as array item as a new option to the second select.

function selectFoods(foodGroup) {
    // Get a reference to the foods select.
    var foodsSelect = document.getElementById("foods");
	
	// Create a two dimension array containing foods for each group.
	var foods = [["Banana","Grapes","Oranges","Watermelon"],
				["Brocolli", "Califlower","Spinach","Tomatoes"],
				["Beef", "Chicken", "Turkey", "Tuna"],
				["Cheese", "Ice Cream", "Milk", "Yogurt"],
				["Bread", "Pasta", "Rice", "Quinoa"]];
				
	if ((foodGroup >= 0) && (foodGroup <= foods.length)) {
		foodsSelect.options.length = 0;

		// Index was in range, so access our array and create options.
		for (var i = 0; i < foods[foodGroup - 1].length; i++) {
		   foodsSelect.options[foodsSelect.options.length] = new Option(foods[foodGroup - 1][i], i);
		}

	}
}

This implementation has a bit of problems when it comes to flexibility so it is suggested that this type of implementation be used for lists that relatively small and undergoes very little change. The advantage to something like this is that you don’t need to have a database connection or create any server-side script like we use in method 2. It is great for those do it yourself type of people that might be doing a business page or have limited server access and resources.

jQuery, JSON and PHP Way

The second method uses jQuery (a framework built using JavaScript… 1.5 or above for our example) and a server-side language (here PHP) to connect to a database, pass it the id of the group and have PHP return a response in JSON or (JavaScript Object Notation). Sounds like a lot of things to build this with but it is pretty straight forward if your site already has jQuery setup.

Using our HTML code example, minus any change event if you added one, we are going to bind a change event to it using jQuery. We will use an $.ajax() call to call our PHP script which will query the database for us using the food group ID we give it as a parameter. It will generate a result set in JSON which our JavaScript will get back as a reply. It will be a simple array that we then loop through and add the options to the foods select drop down. Here is how that might look…

$(function() {
	$("#foodgroups").change(function() {
        var groupID = $(this).val();
	
		$.ajax({
		    type: "GET",
			url: "http://www.example.com/getfoodgroups.php",
			data: { id: groupID },
			dataType: "json"
		}).done(function(reply) {
		    // Clear options
			$("#foods").find("option").remove();
			
			// Loop through JSON response
			$.each(reply, function(key, value) {   
				$('#foods').append($('<option>', { value: value.foodid }).text(value.name)); 
			});
		});

	});
});

When the AJAX is called it will be in the format http://www.example.com/getfoodgroups.php?id=5 if we selected the “Grains” food group. The PHP script will then use the ID to lookup the records it needs to in the database, formulate a JSON reply and return it to the JavaScript above where it will then loop through each result of the reply and append new option objects to the foods select.

So here is an example of how you might do the PHP script….

<?php
	try {
		$con = new PDO("mysql:host=localhost;dbname=dbname", "username","password",array(PDO::MYSQL_ATTR_INIT_COMMAND => "SET NAMES utf8") );
	}
	catch (PDOException $e) {
		echo "Sorry, there was an error connecting to the database.";
	}
	
	if (isset($_GET["id"])) {
		$stmt = $con->prepare("select foodid, name from foods where groupid = ?");
		$stmt->bindValue(1,$_GET["id"]);
		
		// Fetch the foods using the group id
		if ($stmt->execute()) {
			$result = $stmt->fetchAll(PDO::FETCH_ASSOC);
			
			// If there are results, json encode them as the reply.
			if ($result) {
				echo json_encode($result);
			}
		}
	}
?>

This PHP script simply does a simple lookup on our foods table and returns two fields… foodid and name. These are the values that we are going to use back in our AJAX jQuery script to then populate the foods select drop down. That is all there is to it. When testing a setup like this I suggest you always test the PHP script first and use the URL to pass it some parameters and look at the results. Once you get the PHP script working fine THEN move on to the jQuery that way you know that if something is not working, it is the JavaScript that is broken and not your server-side code.

The old way

The third way is the old method similar to method 2 above, but just involves passing the current page the ID of the food group selected and refreshing the whole page, using the ID passed to then look up the foods on the server-side and creating the drop down with the appropriate returned records. This method is not encouraged because it would not be very user friendly and would require the page to be completely reloaded each time you selected a new food group. This is terribly slow and a waste of bandwidth for your visitors.

So with these three methods in mind, use the one you think would be best for your current setup. If you can implement any of them, I would recommend method 2 since it provides the most flexibility and is easily extensible. You can modify the results returned on the server-side code and it will immediately start populating drop downs in real time without any modifications to the JavaScript. These are only 3 of a plethora of options and configurations. You will need to modify these scripts I have provided here to better suit your database or web page design. But as you can see, the basics are there.

Thanks again for reading! 🙂

About The Author

Martyr2 is the founder of the Coders Lexicon and author of the new ebooks "The Programmers Idea Book" and "Diagnosing the Problem" . He has been a programmer for over 25 years. He works for a hot application development company in Vancouver Canada which service some of the biggest tech companies in the world. He has won numerous awards for his mentoring in software development and contributes regularly to several communities around the web. He is an expert in numerous languages including .NET, PHP, C/C++, Java and more.