Last updated by
4 years ago
Page: AJAX-Driven SELECTs in GSP, Version:4
AJAX-Driven SELECTs in GSP
A common pattern that pops up in Web development is the need to have one SELECT box change the contents of another SELECT box on the same page without doing a refresh.Take the following domains as an example:class Country {
String name
String abbr
String language static hasMany = [cities:City]
}class City {
String name
String timezone static belongsTo = [country:Country]
}import grails.converters.*class CountryController { def ajaxGetCities = {
def country = Country.get(params.id)
render country?.cities as JSON
}
}$ curl "http://localhost:8080/widgetco/country/ajaxGetCities/1"[{"id":4,"class":"City","country":1,"name":"Dallas","timezone":"CST"},{"id":1,"class":"City","country":1,"name":"New York","timezone":"EST"}]"
<g:javascript library="prototype" /><form>
<g:select
optionKey="id" optionValue="name" name="country.name" id="country.name" from="${Country.list()}"
onchange="${remoteFunction(controller:'country', action:'ajaxGetCities', params:''id=' + escape(this.value)', onComplete:'updateCity(e)')}"
></g:select>
<g:select name="city" id="city"></g:select>
</form><g:javascript> function updateCity(e) {
// The response comes back as a bunch-o-JSON
var cities = eval("(" + e.responseText + ")") // evaluate JSON if (cities) {
var rselect = document.getElementById('city') // Clear all previous options
var l = rselect.length while (l > 0) {
l--
rselect.remove(l)
} // Rebuild the select
for (var i=0; i < cities.length; i++) {
var city = cities[i]
var opt = document.createElement('option');
opt.text = city.name
opt.value = city.id
try {
rselect.add(opt, null) // standards compliant; doesn't work in IE
}
catch(ex) {
rselect.add(opt) // IE only
}
}
}
}
// This is called when the page loads to initialize city
var zselect = document.getElementById('country.name')
var zopt = zselect.options[zselect.selectedIndex]
${remoteFunction(controller:'country', action:'ajaxGetCities', params:''id=' + zopt.value', onComplete:'updateCity(e)')}</g:javascript>