-2

I have a Grails (2.3.6) app serving an HTML form with two <select/> elements in it: one that allows users to select a country and then, subsequently, a state. When the user selects a new country, I want to update the state select element. To do this, on country change(), I need to ask the server for the new list of state options to populate the state <select/> with:

<div class="blah">
    <label for="state">State</label><br/>
    <g:select id="state" name="state" from="${states}" />
</div>

<script type="text/javascript">
    jQuery('#country').change(function() {
        var countryName = $('#country option:selected').val();

        jQuery.ajax({
            url: "getStateListByCountry",
            type:"get",
            dataType: 'json',
            data: {
                countryName: countryName
            },
            success: function(data) {
                alert("Received following from server: " + data);

                $("#state option").remove();

                $.each(data, function(key, value) {
                    $('#state')
                        .append($("<option></option>")
                        .attr("value",key)
                        .text(value));
                });
            },
            error: function(xhr){
                alert(xhr.responseText); //<----TODO: Replace
            }
        });
    });
</script>

And then, on the Grails/server side:

class MyController {
    // Stub this with dummy data to return.
    def getStateListByCountry() {
        List<String> states = new ArrayList<String>()
        states.add("NY")
        states.add("NH")
        states.add("VT")

        println "Sending the following back to browser: ${states}."

        states
    }       
}

At runtime, when I select a new country in the '#country' select, I see the following message in the Grails app log:

Sending the following back to browser: [NY, NH, VT].

But then in the browser I get an alert(...) that prints the HTML of my custom "Page Not Found" error page!

Furthermore my '#state' select doesn't update with the 3 dummy state values. So the Grails server is correctly receiving the client request, and trying to send back my dummy state list, but somewhere along the way a "Page Not Found" template is getting returned. Any ideas as to what is going on here or what is wrong with my code?


Update

It seems that my error function is executing, and the bizarre HTML I've been seeing inside the alert is actually the xhr.responseText passed into that method.

The Grails server isn't reporting any errors in the logs, and a println in the getStateListByCountry method confirms that the JSON being returned to the client is ["NY","VT","NH"]. So it seems that the server is returning an error somehow, and jQuery is executing the error handler, not the success handler...ideas?

smeeb
  • 27,777
  • 57
  • 250
  • 447

3 Answers3

4

Try to add a: "as JSON" in states:

states as JSON

EDIT:

smeeb, I made a test environment here and changed your:

jQuery.ajax({
    url: "controllername/getStateListByCountry",
    type: "get",
    data: countryName,

to use the controllername before the actio, no need for dataType, and the return to:

render states as JSON

and It worked, can you try it?

Vitor Hugo
  • 1,106
  • 1
  • 15
  • 35
  • Thanks @Vitor Hugo (+1) - however this doesn't fix my issue; same exact problem. Any other ideas? – smeeb Oct 31 '14 at 14:57
  • Also, please see my update, the `error` handler is executing, which is why I'm seeing bizarre response text from the server... – smeeb Oct 31 '14 at 15:07
2

Call a function on change of country

   jQuery('#country').change(function() {

    jQuery.ajax({
        url: "getStateListByCountry",
        type:"get",
        dataType: 'json',
        data: {
            countryName: countryName
        },
       success: function(data) {
        $('#divId').replaceWith(data);

    }

and on the specified url getStateListByCountry retrieve states and render a template from there

render template: 'nameOfTemplate', model: [states:States.list()]

and then replace the div with new template in you success call back.

In the template you should put g:select box and populate that select box with states list passed in model. You can create template as you are creating view only you have to put an underscore "_" before the name of template. More about Templates and Views

ABC
  • 4,263
  • 10
  • 45
  • 72
  • Thanks @Abdullah (+1) - although this is an interesting solution I'm not interested in it for this particular problem. Please see my update; it looks like the `error` handler is executing, which is why I'm seeing the bizarre response text. Any ideas? Thanks again! – smeeb Oct 31 '14 at 15:08
1

The problem was on the client-side. I had specified a dataType of "json" but was not returning JSON via the Grails render(...) method.

smeeb
  • 27,777
  • 57
  • 250
  • 447
  • I added some things to my answer, please check it out. – Vitor Hugo Oct 31 '14 at 16:27
  • Regarding the bounty: It doesn't work like you expected. Have a look at [How bounty is awarded](http://stackoverflow.com/help/bounty) (You cannot award a bounty to your own answer.) :) – dmahapatro Nov 03 '14 at 19:03
  • 1
    Thanks @dmahapatro but my intention was never to award myself the bounty. That's like giving yourself a zero-interest loan; why do it? – smeeb Nov 05 '14 at 13:44