Multiple Related Select Lists

(Return to Main Code Corner Page)

One question that frequently appears in help forums has to do with linking multiple select lists on a web form, for example, when a user selects a particular state, the select list comprising cities would only display the relevant values for that particular state. In another article, I show how one can submit the form to itself and use the request object as a parameter to create server-side SQL selects.

Sometimes, however, you may not want to make multiple trips to the server. In this article, I show how you can user client-side JavaScript arrays to create the same result. This solution may not be appropriate for large sets of data or for data that is very dynamic, but it is still a useful technique to have in your arsenal.

For this discussion, we will take as the example car makes and models, the goal being that a selection from manufacturers drop down will populate the model select list with the corresponding models. See the code in action here.

The key to creating a client-side solution lies in populating the models with select lists from an array that corresponds to the value from the manufacturers select list. With multi-dimensional arrays, that would be a simple matter, but JavaScript does not support them. Fortunately, however, we can create something called associative arrays, which allow you to form a link between one array and another. Consider Example 1:

<SCRIPT LANGUAGE=javascript>
<!--
arrModels = new Array(3)
arrModels [0] = new Array(1)
arrModels [1]= new Array(3)
arrModels [2] = new Array(4)
//Empty (0)
arrModels [0][0.0] = " "
//Ford (3)
arrModels [1] [0] = "Tempo"
arrModels [1] [1] = "Tauras"
arrModels [1] [2] = "Windstar"
//Toyota (2)
arrModels [2][0] = "Tercel"
arrModels [2][1] = "Corolla"
arrModels [2][2] = "Camry"
arrModels [2][3] = "Avalon"
//-->
</SCRIPT>

I start by creating an array called arrModels. The tricky bit is that I immediately assign the value of a new array to each of the array elements. Next, I populate each of these arrays with values that I will need for my select lists: an empty value for the default selection--arrModels[0]; the Tempo, Taurus, and Windstar for the Ford selection--arrModels[1]; and the Tercel, Corolla, Camry, and Avalon for the Toyota selection arrModels[2].

As will become clear later in the code, we can use the selected index from the manufacturer select list to point to the related associative array, and then iterate through that array to populate the models select control.

This approach, however, suffers from a deficiency. It will work fine if I don't want to specify a value attribute for the select control or if I want to have the same text for both the display and value attributes. If I want to have separate text for the value and for the display, then I need to modify my array structures somewhat. Example 2 shows the necessary modification:

<SCRIPT LANGUAGE=javascript>
<!--
arrModels = new Array(3)
arrModels [0] = new Array(1)
arrModels [1]= new Array(3)
arrModels [2] = new Array(4)
//Empty (0)
arrModels [0][0.0] = " "
arrModels [0][0.1] = " "
//Ford (3)
arrModels [1] [0.0] = "economy:tempo"
arrModels [1] [0.1] = "Tempo"
arrModels [1] [1.0] = "luxury:taurus"
arrModels [1] [1.1] = "Tauras"
arrModels [1] [2.0] = "minivan:windstar"
arrModels [1] [2.1] = "Windstar"
//Toyota (2)
arrModels [2][0.0] = "economy:tercel"
arrModels [2][0.1] = "Tercel"
arrModels [2][1.0] = "midprice:corolla"
arrModels [2][1.1] = "Corolla"
arrModels [2][2.0] = "luxury:camary"
arrModels [2][2.1] = "Camry"
arrModels [2][3.0] = "moneytoburn:avalon"
arrModels [2][3.1] = "Avalon"
//-->
</SCRIPT>

While this structure is somewhat more complex, it will allow us to specify a separate item for the value and the display text.

The next step is to create the code that uses the selected index from the manufacturers select list to populate the models select list. The code is in example 3.

<SCRIPT LANGUAGE=javascript>
<!--
function FillList(){
    var objForm = document.forms['frmMultipleSelects'];
    var objSelectModels = objForm.elements['strModels'];
    var intArrayIndex= objForm.elements['strManufacturer'].selectedIndex;
    objSelectModels.selectedIndex = 0;
    objSelectModels.length =0;
    for (i=0;i<arrModels[intArrayIndex].length;i++){
     objSelectModels.options[i] = new Option()
         objSelectModels.options[i].value = arrModels[intArrayIndex][eval(i + ".0")]
         objSelectModels.options[i].text = arrModels[intArrayIndex][eval(i + ".1")]
     }
     objSelectModels.focus() ;
}
//-->
</SCRIPT>

The first couple of lines declare some variables and set the values from the form elements to them. The next two lines reset the models select list to remove any existing elements and to set the selected index to 0. With that out of the way, we can use the new Option() method to dynamically create options for our models select object and use the .value and .text properties to populate them with the values from the arrays. The naming convention in the associate arrays allows a simple counter to iterate through and grab the values. The final line sets the focus to the models control.

Even though I have set this example for two select lists, it could easily be expanded to three or more lists. By passing two para maters to the FillList() function--the name of the two select lists--you could generalize and expand this approach.

The source for the whole page is available here.

(Return to Main Code Corner Page)

If you found this article helpful and you would like to make a donation, please click on the PayPal button below.