From time to time, I run into the following problem. A User has to fill in a form containing 2 drop down lists, and I need to populate the second one with options that depend on the selection made on the first select box. This problem, commonly known as 'Chained Selects' can be easily solved using a dusting of ajax magic.
To demonstrate this feature, I'm using a simple example containing 2 domain classes, Family and Member. These are listed below,
The example revolves around 2 drop down lists. The first of these lists families, e.g. Simpsons and Griffins [Family Guy]. Now I want the second drop down list to be correctly populated with the family members depending on the selection made to the first drop down list.
Step 1: Import 'prototype'
We're going to use prototype to implement this feature. Note you're not restricted to using this library. Others such as jQuery will do an equally impressive job. So the first step is to import in the library as follows,
Step 2: Implement 2 drop down lists
Next we need to implement the 2 select elements as so,
Step 3: Hook up the ajax code
Here we do a couple of things; first of all we attach a listener to the 'familySelect' element to detect for any 'change' events fired when a User makes a selection on this element. Secondly we implement the ajax function that will be triggered when such an event is detected. In this instance we're using prototype's Ajax.Updater() function, which takes a number of arguments that are fully documented elsewhere. The first argument is the id of the element that will be updated by the response to the ajax function. In our case this will be a second drop down list. The second argument is a url pointing to a grails action to service our ajax request. Finally we have a set of optional parameters, the important one being 'selectedValue' which will hold the selection made by the User on the first drop down list.
Step 4: Write the grails action
This the grails action that will service the ajax call. Quite simple really. It takes the value selected from the Family dropdown list and uses it to retrieve the corresponding Domain object. This object is then supplied to a tempate file that is subsequently returned as a response to the ajax function in step 3.
Step 5: Write the HTML to update the page.
This is the HTML that will be used to update the page by the ajax function defined above. Note that since I'm using templates, I need to save this in a file whose name should be prefixed with an underscore, '_'.
And here is the final result.
When we select 'Simpsons' as the Family, the second drop down is correctly populated with the members of the Simpson family.
Conversely, if we select 'Griffin' as the family, the second drop down list is populated with the members of the Griffin family.
As a final note, this example could be improved by displaying a default set of values for both selects, when the page is first loaded.
You can download the code [chainSelectFamily.zip] from here.