With Grails domain classes, constraints can be specified – including the maximum size of a String. For example:
class Book {
String title
static def constraints = {
title(maxSize:20)
}
}
When using ‘grails generate-all’ to create scaffolding, you’ll notice that create.gsp and add.gsp hardcode the maxlength attribute:
<input type="text" maxlength="20" id="title" name="title"
value="${fieldValue(bean:book,field:'title')}"/>
It is possible to directly reference the constraint, meaning that the maxlength attribute is not hardcoded – and thus only defined once (in the domain object):
<input type="text" maxlength="${Book.constraints.title.getMaxSize()}"
id="title" name="title"
value="${fieldValue(bean:book,field:'title')}"/>
In fact, we can go even further and create a tag where we pass in the object itself, and the name (which matches the property name) and we can dynamically generate the maxlength and value attributes.
So when editing a book with the title set to ‘my new book’, the following code:
<jttext:textField object="${book}" name="title"/>
produces the following HTML:
<input type="text" name="title" maxlength="20" value="my new book"
id="title" />
The tag library to produce this is as follows:
import org.codehaus.groovy.grails.plugins.web.taglib.FormTagLib
class TextTagLib extends FormTagLib {
static namespace = "jttext"
def textField = {attrs ->
attrs.type = "text"
attrs.tagName = "textField"
def object = attrs.remove('object')
def maxlength = object.constraints."${attrs.name}".getMaxSize()
if(maxlength) {
attrs.put('maxlength', maxlength)
}
attrs.put('value', fieldValue(bean:object,field:attrs.name))
def result = field(attrs)
if (result) {
out << result
}
}
}
It makes sense to me that the tag does all of the work – it reduces duplication and makes the code more readable.
What do you think?






{ 6 comments… read them below or add one }
It makes absolute sense. Especially when one is using command objects with some specific settings. using this aproach one can avoid inconsistency . is it working with Command Objects as well?
David
David, I’m not sure what you mean here – it makes sense with Domain objects since they are populated with constraints such as maxSize. What do you mean by command objects?
I mean this Grails feature
http://grails.org/doc/1.0.x/guide/6.%20The%20Web%20Layer.html#6.1.9%20Command%20Objects
Its like the domain object except it serves as form. Details are in docs.
Ah, thanks. I expect it will work with command objects since constraints are defined in exactly the same way.
‘Command Objects’ is very unusual naming.
They should call it Forms or something.
Thanks for showcasing this example. But, I guess this doesn’t works for nested level fields.
For ex.
Class A has a instance of Class B as a field b, which in turn has field String title. Then in that case following line will not work, until ‘b’ is already initialized
maxlength=”${A.b.constraints.title.getMaxSize()}”