Special page directives

namespace: the optional namespace for the tag

docs: standard tag documentation that will end up in the generated taglib and can be used by your IDE for code completion purposes.

Required attributes

Adding "gsptaglib.addRequiredAsserts = true" to BuildConfig.groovy, will insert assert statements for attributes that are marked as required in the tag docs. Tag users will then get a clear error message when they don't specify a value for the attribute.

Dependency injection

Code blocks that start with "@TagLibCodeBlock" will be put at class level of the generated taglib, meaning that they can be used to define class members that get auto-wired:

Code generation

For each GSP under grails-app/taglib, a corresponding _MytagGspTagLib.groovy will be generated if it does not exist yet or if it is older then the GSP.
The code generation is triggered by a grails compile or by changing the GSP during a grails run-app.

Layout tags

Reusable layouts are achieved in Grails by using Sitemesh. While this is OK for global page layouts, it is not convenient for writing reusable UI components that provide a layout template (with template I mean the design pattern, not a grails GSP template).
F.e. if you frequently use boxes with a header and 2 columns, you would write a box tag and use it as follows:

The box tag could then generate a html table and put the header, left and right parts in the respective td's. You can then even nest boxes inside other boxes etc., without having to duplicate the layout html for every usage.

Writing layout tags

When you want to create a layout tag, you need a way to capture the output of all the parts before the layout tag can render itself. This is where the LayoutWriterStack comes in:

def box={attrs, body->
def parts= LayoutWriterStack.writeParts(body)
out << "<table>"
out << "<tr><td colspan='2'>" << parts.header << "</td></tr>"
out << "<tr><td>" << parts.left << "</td><td>" << parts.right << "</td></tr>"
out << "</table>"
//everything inside the box tag that is not within the header, left or right tag, is still accessible in the 'body' part
out << parts.body
}

I.s.o. writing to @out@, the header, left and right tags need to write their contents to their respective parts: