Example Problem
A contrived for dynamic dropdowns can be described below:
A user would like to select a sports team for a city. The user first selects a value for a dropdown to choose a city. A second dropdown is filtered with the sports teams within that city. An example to clarify:
- The user selects Dallas as the city in the first dropdown. The second dropdown now displays values: Mavericks, Cowboys and Rangers.
- The user selects Pittsburgh as the city in the first dropdown. The second dropdown now displays values Steelers, Pirates, and Penguins.
High Level Design in Grails
Before we get into the details, we can take a step back and describe how we can accomplish a dynamic dropdown in the grails framework.
- On a gsp page, create a select dropdown with the list of cities.
- On change of the city dropdown, send an ajax call to the server with a param of the city selected.
- A controller on the server receives the parameter and looks for teams based on the city selected.
- Return a template with a new select dropdown for the teams, providing a model with the filtered list of teams.
Domain Objects
The domain objects for this example are quite simple: A City object with a name, and a Team object.
package dropdown
class City {
String name
static hasMany = [teams: Team]
static constraints = {
}
}
package dropdown
class Team {
String name
static belongsTo = Team
static constraints = {
}
String toString() {
name
}
}
Gsp Page
A gsp page contains a list of the cities directly from a GORM call. This is commonly performed and demonstrated by the default generated grails gsp pages. Note the use of remoteFunction. This is a grails gsp utility which makes an ajax call to the server and provides 'update' for the section of the dom to be updated on return.
For the team dropdown, we will start off with a an empty select tag. Below is a snippet.
<g:select name="city.id" from="${City.list()}" optionKey="id" optionValue="name"
noSelection="['':'Choose City']"
onchange="${remoteFunction (
controller: 'city',
action: 'findTeamsForCity',
params: '\'city.id=\' + this.value',
update: 'teamSelection'
)}" />
....
<td id="teamSelection" valign="top">
<select>
<option>Choose Team</option>
</select>
</td>
Controller used for Filtering
The controller will have a closure which takes in the city id, and then uses it to provide the teams associated with the city. This closure is invoked via ajax. The closure renders a template and a model.
The def dynamicDropdown closure is just used for navigation. By convention its renders the gsp of the same name.
package dropdown
class CityController {
static scaffold = City
// just navigation to the gsp
def dynamicDropdown = {
}
def findTeamsForCity = {
def city = City.get(params.city.id)
render(template: 'teamSelection', model: [teams: city.teams])
}
}
TemplateThe template is used to replace a section of the dom in the gsp. It accepts any model that is provided.
<!-- This template renders a drop down after a city is selected -->
<g:select name="team.id" from="${teams}" optionValue="name"
optionKey="id"/>
Conclusion
There are multiple ways to accomplish a dynamic dropdown. Native jQuery can be used, or even native JavaScript. I chose to utilize the built-in functions of grails and lessen my dependency on client side programming. This proved to be clean, quick and quite simple!
Grails 2.0.1 complains about this line
ReplyDeleteparams: ''city.id=' + this.value',
Even after getting around that, this code won't dynamically fill the teams dropdown - however, the relationships do work.
Did you test this code? Do you have a working sample project which you might share?
Thanks
This code is working code that i pasted on to the site. Unfortunately the tool i used to format html on to the blog left out a '/' char, and it was escaped.
ReplyDeletethe snipper should lool like this:
params: '\'city.id=\' + this.value',
If you would like a zip of the code, send me an email please. I will be glad to send it to u. I have corrected on the site.
Thanks for catching that!
Can you send me the code. Much appreciated.
ReplyDelete@cmtopinka
ReplyDeletei sent the code to cmtopinka@gmail.com. Is that your email? If not please let me know
Thank you! :)
ReplyDeleteHi
ReplyDeletecan u send me the code to karthiknagtaurus@gmail.com
Hello, can you also email me the code at rachel_bird@taylor.edu?
ReplyDeleteThanks so much.
Plz u send me the code kamonpop@gmail.com
ReplyDeletePLease send me the code at saurabhkr1@yahoo.com . Many Thanks in advance
ReplyDeleteHello, Can you send me the code, please? Thank you
ReplyDeletelletuga15@gmail.com
Hi , can you please send me the code, too? I tried to google it with no luck.
ReplyDeleteerik.marencik[at]gmail[dot]com
i have to create the samething , but the value of first select to be tested. for eg: it belongs to province ="BC" something like that.
ReplyDeleteOne morething , these two select tag to be used in the create.gsp page does it affect other user data already entered?
Can you please give me reply and code to my id :kalpana.vasan@gmail.com
Hi. I was wondering if you could share the source with me as well. Thank you! ahdunn@gmail.com
ReplyDelete