Search code examples
formsgrailsgsp

Grails forms & URL mapping


I am writing a Grails app where I would like to setup a form that allows a user to type in an image ID number and this value will be passed to a controller / action that retrieves the image from S3 for the given image ID.

The desired url would be of the format example.com/results/1234. I have setup the following URL mappings:

class UrlMappings {

    static mappings = {
        "/$controller/$action?/$id?"{
            constraints {
                // apply constraints here
            }
        }

        "/results/$id?" {
            controller = "s3Image"
            action = "getS3Image"
        }

        "/"(view:"/index")
        "500"(view:'/error')
    }
}

The following is how I have setup a form:

<g:form  controller="results" method="get">
    <input type="text" name="id" class="input-xxlarge" placeholder="http://www.example.com">
      <button class="btn btn-inverse">Submit</button>
</g:form> 

However this seems to submit the form to example.com/results?id=12345.

How would I alter my form or mappings such that I can produce the desired url after form submission?

Thanks!


Solution

  • <g:form  controller="results" method="get">
    

    will generate an HTML form whose action URL is /results (the reverse URL mapping for a controller named "results" with no action or id). When this form is submitted, the browser will add ?id=1234 to the end of this URL because the form method is GET. This is not something you can influence in your URL mappings on the server side.

    Instead, you should have your form POST to a different controller action that redirects to the getS3Image action. The redirect will have access to the ID on the server side, so can generate the friendly-looking URL for the redirect.

    UrlMappings:

    "/results/$id?" {
        controller = "s3Image"
        action = "getS3Image"
    }
    
    "/findImage" {
        controller = "s3Image"
        action = "find"
    }
    

    S3ImageController:

    def find() {
        redirect(action:"getS3Image", id:params.id)
    }
    
    def getS3Image() {
        // as before
    }
    

    GSP:

    <g:form  controller="s3Image" action="find" method="post">
        <input type="text" name="id" class="input-xxlarge" placeholder="http://www.example.com">
          <button class="btn btn-inverse">Submit</button>
    </g:form>