smeeb
smeeb

Reputation: 29477

Grails injection of g:select and jQuery handler

I have the following Grails (2.3.6) POGO:

class Pet {
    Long id
    String name
    PetType type
}

And the following controller:

class PetController {
    def index() {
        List<Pet> pets = PetLoader.loadAllPets()
        render(
            view: "listPets",
            model: [
                pets: pets
            ]
        )
    }

    def loadPet() {
        Long petId = params.petId   // Pet#id
        // Do stuff with the 'petId'.
    }
)

And in the body of the respective listPets.gsp:

<body>
    <h1>Select a pet to edit below:</h1>

    <g:select id="pets"
        name="pets"
        from="${pets}"
        value="${pet.name}"
        optionKey="id" />

    <g:javascript>
        var ajaxAction = "${createLink(controller:'pet',action:'loadPet')}"
        $("#pets").on('change', function() {
            $.get(
                url: ajaxAction,
                data: $("#pets").val(),
                success: function(data, status) {
                    alert("Success!\n" + data);
                },
                dataType: "json"
            );
        });
    </g:javascript>
</body>

When I run this code, I get an empty <g:select> that is obviously not injected/configured correctly. What I want to do is this:

  1. When the page loads, the entire users list gets injected into the <select id="pets"> drop-down and displays the Pet#name String as the option text; then
  2. When the user selects a new Pet from the drop-down (in the UI), the jQuery handler fires an asynch call to loadPet; then
  3. Inside loadPet, I need acccess to the Pet#id of the selected value in the drop down, via the params object, so that I can do other stuff with that pet id in the backend

I'm having a tough time seeing the forest through the trees here. I'm definitely sure that I botched the <g:select> tag. But I may also need to make changes to the controller and/or jQuery script. So I ask: What changes do I need to my code so that the select is populated with Pet#name, but, when loadPets is called from the jQuery, I have access to the Pet#id from the params?

Upvotes: 0

Views: 1088

Answers (1)

Andrew
Andrew

Reputation: 2249

Modifying your code slightly, here is an example that (I believe) does what you intended. Here are the key changes:

  1. Within g:select, use optionValue and optionKey to control the display string and underlying <option> value. For more detail and examples, see: http://grails.org/doc/latest/ref/Tags/select.html
  2. Your jQuery code uses the .get() shorthand, but .ajax() parameter syntax. Either could be made work, but there are differences in the function parameters. See: http://api.jquery.com/jquery.get/
  3. I included a CDN link to jQuery. This is useful for quick tests, but there are a variety of other ways to include the jQuery library (and you may already have this configured in your project)
  4. createLink is wrapped with raw() to ensure that the URL produced is not escaped.

Updated Code:

No changes to Pet or PetController

listPets.gsp

<!DOCTYPE html>
<html>
  <head>
  <meta name="layout" content="main"/>
  <script src="//ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>
</head>
<body>
    <h1>Select a pet to edit below:</h1>

    <g:select id="pets"
        name="pets"
        from="${pets}"
        optionKey="id"
        optionValue="name" />

    <g:javascript>
        var ajaxAction = '${raw(createLink(controller:'pet',action:'loadPet'))}';
        $("#pets").on('change', function() {
            $.ajax({
                url: ajaxAction,
                data: { petId: $("#pets").val() },
                success: function(data, status) {
                    alert("Success!\n" + data);
                }
            });
        });
    </g:javascript>

</body>
</html>

Upvotes: 1

Related Questions