0

I'm trying to chain two, possibly three <g:select ...> statements together using Ajax like is shown here Populate dropdown list using ajax In grails but all the examples I find have two big differences from what I'm using. 1. I'm using the jQuery library, not prototype. And 2. I don't have domain objects for my select values, they are pulled from an Oracle table via a service call.

My problem looks like this:

<g:select name="degreeSubject" from="${majors}" noSelection="${['':'-Choose Subject-']}" value="${degreeInstance?.degreeSubject }"/>
<g:select name="degreeConcentration" from="${concentrations}" noSelection="${['':'']}" value="${degreeInstance?.degreeConcentration }"/>

Where the majors, and concentrations come through the controller but are populated in a service class.

I was thinking the controller method would look something like

def updateSelect = {
    def concentrations = degreeService.getConcentrations(params.selectedValue)
    render (template:"selectConcentration", model : ['concentrations' : concentrations])

}

But, I can't get it to work.

Thoughts? Or someone have an example of doing this with jQuery and no domain objects using Grails 2.2.4?

Community
  • 1
  • 1
idonaldson
  • 465
  • 1
  • 14
  • 33

1 Answers1

1

You can really do it without being javascript-library specific. If you use the grails built-in remoteFunction it will handle the jQuery portion for you. What you would then want for your degreeSubject select is:

<g:select name="degreeSubject" 
          from="${majors}" 
          noSelection="${['':'-Choose Subject-']}" 
          value="${degreeInstance?.degreeSubject }"
          onChange="${remoteFunction(
            controller: 'yourControllerName', 
            action: 'updateSelect', 
            params: '\'value=\' + escape(this.value),
            onSuccess: 'updateConcentration(data)')}/>

The key being the onChange event calling the remoteFunction. The remote function will make an ajax call to whatever controller action you want, but you'll need to call a javascript function to take in the results of your controller action and populate the other select. If you wanted to do this with simple js you could do this:

function updateConcentration(items) {
    var control = document.getElementById('degreeConcentration')

    // Clear all previous options
    var i = control.length
    while (i > 0) {
        i--
        control.remove(i)
    }

    // Rebuild the select
    for (i=0; i < items.length; i++) {
        var optItem = items[i]
        var opt = document.createElement('option');
        opt.text = optItem.value
        opt.value = optItem.id
        try {
                control.add(opt, null) // doesn't work in IE
        }
        catch(ex) {
                control.add(opt) // IE only
        }
    }
}

and finally your controller action should look like this:

def updateSelect(value) = {
    def concentrations = degreeService.getConcentrations(value)
    render concentrations as JSON // or use respond concentrations if you upgrade to 2.3
}
Jim Sosa
  • 578
  • 3
  • 21