Last updated by admin 5 years ago

Smarter Grails Tags

While the tags in grails provide a lot of useful features, there is room for improvement. This page outlines some ideas for improvements of the different tags. Feel free to expand this article to other tags.

Form Tags

The biggest area for improvement is with form tags. This is one area the grails tags seem to provide less functionality then other web frameworks. The improvements suggested here are to do with automatically rendering specific classes on input tags when in error and fetching the correct field value instead of having to do these things with function calls in expressions for each tag.

For example, the following tag which is pretty standard for all grails applications:

<g:textField name="username" value="${fieldValue(bean:user,field:'username'}" class="${hasErrors(bean:user,user:'username', 'errors')}" />
Would be replaced with one of the following:
<g:textField bean="user" field="username" />
or
<g:textField name="user.username" />
The first suggested replacement tag is probably more in line with the grails standard. It specifies the bean and field for which the tag applies. The second example is taken from other web frameworks like Stripes which performs automatic data binding for selected objects on its version of controllers. It probably isn't appropriate for the grails taglib but provides the inspiration for the suggested change.

The replacement tags suggested should operate exactly as the example tag given. It should fetch its value from the correct place on the bean and would result in the rendered html tag having a class of error when there is an error for that field on the bean. This approach has a couple of advantages. The first is that basic and common tag functions used so often with grails form input tags like fetching a field's value and rendering an error class are handled transparently. The second is, while these behaviors are available to make the writing of forms in grails easier, you can always use an alternative method. Other attributes such as maxlength can also be automatically populated for textFields where the constraint maxSize is specified (See http://www.javathinking.com/?p=70 for more information).

Rendering Tags

The suggestions for render tags are born out of the way I personally deal with navigation and sorting on a list page. Given this, I'll start by explaining how I deal with navigation before presenting my suggestions.

In my grails applications, I have a navigation command I like to use. The source is below.

class NavigationCommand implements Serializable {
    Integer max = 20
    Integer offset = 0
    String sort = ""
    String order = "asc"
}
I like being able to separate this parameters away from the logic of an action*. There is a down side of this approach though. In my actions, I have to copy across he values from the command to the params in my action so the paginate and sortableColumn tags can have access to them. Born from this frustration is the following suggestion. Tags like paginate and sortableColumn should have a bean attribute where it first looks for the parameters it needs. For example, to use my navigation command assuming I have the following list action:
def list { NavigationCommand nav ->
    // Some code
    …
    [ total : total, ..... ]
}
I should be able to use the following tag:
<g:paginate total="${total}" bean="${nav}" />
The paginate tag would fist look at the nav bean for max, offset etc. before checking params. This can also be applied to other tags like sortableColumns.

* NOTE: Another reason for separating the navigation into a separate command is that I use a custom paginate tag that allows a user to set how many rows they can view on a page. Having this meant I was constantly dealing with max and offset in my params which started to become a pain. A screen shot of my custom paginate page is in attachments. If you like it, maybe it could also be added into grails.