Search code examples
grailscommand-objects

Grails best practice on form redirection/rendering


If I have an action def formPage(), I want to be able to save the form on that page, show the form with the previously entered values if there's an error, and show a blank form if it's a success.

My question is: Is it best practice for formPage to call something like saveFormPage(FormPageCommand fpc)? saveFormPage can then render formPage with or without the previously entered values. The problem with this approach is that the user can click the address bar, press enter, and then get a slew of errors since the form hasn't been filled in, and the command object sees all the null or blank values.

Another approach might be to just have a def formPage(FormPageCommand fpc), and ignore errors and just show a blank form if none of the values are filled in.

One might also call saveFormPage(FormPageCommand fpc) and redirect back to formPage() if none of the values are filled in.

What is the best practice here?


Solution

  • Try this example:

    Your controller

    class MyFormController {
        def formPage() {
            [cmd: new FormPageCommand()]
        }
    
        def saveFormPage(FormPageCommand cmd) {
            if (cmd.hasErrors()) {
                render view: "formPage", model: [cmd: cmd]
            } else {
                // Process form
                // ......
    
                // Redirect back formPage() to display a new form
                redirect action: "formPage"
            }
        }
    }
    

    Your command object

    class FormPageCommand {
        String optionalValue
        String requiredValue
    
        static constraints = {
            optionalValue(nullable: true, blank: true)
            requiredValue(nullable: false, blank: false)
        }
    }
    

    Your formPage.gsp

    <g:form controller="myForm" action="saveFormPage" method="POST">
    
      <label>Required value *</label>
      <g:textField name="requiredValue" value="${cmd.requiredValue}"/>
      <g:if test="${cmd.errors.getFieldError('requiredValue')}">
        <g:message error="${cmd.errors.getFieldError('requiredValue')}"/>
      </g:if>
    
      <label>Optional value</label>
      <g:textField name="optionalValue" value="${cmd.optionalValue}"/>
    
      <g:submitButton name="submit"/>
    
    </g:form>
    

    It should serve your need.

    Cheers.