Shorter Grails textField

Making textFields in Grails is a bit verbose, at least if you want error highlighting and returned values on errors. This post shows a quick solution.


A full textField would be:

<g:textField class="${hasErrors(bean:user, field:'name', 'errors')}" value="${fieldValue(bean:user,field:'name')}" name="name"/>

Which clearly is very verbose; you have to specify “user” twice, and “name” even three times. This verbosity also makes the view less readable.

Googling for this problem resulted in: Smarter Grails Tags (a proposal). Funny that the writer exactly sees the same problem in it, also uses the “user” domain model, and also knows Stripes where you could just use something like

<stripes:text name="name"/>

and specify the bean name in the form. (Stripes has a very good Quick Start Guide, which also shows error highlighting.)

One of the less verbose proposed formats of textField is:

<g:textField bean="user" field="username" />

Implemented Solution

I found that implementing a quick version of this is surprisingly easy in Grails, it only takes for a few statements. Here is the code:

import org.codehaus.groovy.grails.plugins.web.taglib.FormTagLib

// file: project/grails-app/taglib/MyTagLib.groovy
class MyTagLib {
    // tagname "myTextField" within the "g" namespace
    def myTextField = {attrs ->
        // If a controller returned the bean, and the field has an error,
        // then "errors" will be returned as HTML class, otherwise the class will be empty.
        attrs.class = hasErrors(bean:attrs.bean, field:attrs.field, 'errors')
        // Retrieves the field value of the given bean to be rendered in the view.
        // Note: specify the bean and not the bean name. So "${user}" instead of "user"
        attrs.value = fieldValue(bean:attrs.bean, field:attrs.field)
        // Required for textField taglib. is a keyname of the params map = attrs.field
        // renders the HTML tag
        out << new FormTagLib().textField(attrs)

<g:myTextField bean="$user" field="name" />

And ofcourse some CSS to highlight the error in a color. This can be put in the HTML head (or better, a seperate CSS file) :

<style type="text/css">
   .errors {
      background-color: red;

Leave a Reply

Your email address will not be published. Required fields are marked *