The purpose of this taglib is to define a ui composition pattern to leverage template layout.
The tags
The taglib will expose the following tags :
- ui:composition: The main tag. It takes a template attribute and it has ui:define tags as childrens.
- ui:define: The children tags. It takes a name attribute and
a composition attribute which is a trick to create the parent<->children relationship. The body content of each ui:define tags will be used inside the ui:composition template.
The taglib
Writing taglib in Grails is a breeze on the contrary of frameworks like JSF.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
class UICompositionTagLib { | |
static namespace = 'ui' | |
def out | |
def composition = { attrs, body -> | |
if (!attrs.template) { | |
throwTagError("Tag [composition] is missing required attribute [template]") | |
} | |
Composition composition = new Composition() | |
body(composition) | |
out << g.render(template: attrs.template, model: composition.defines) | |
} | |
def define = { attrs, body -> | |
if (!attrs.composition) { | |
throwTagError("Tag [define] is missing required attribute [composition]") | |
} | |
if (!attrs.name) { | |
throwTagError("Tag [define] is missing required attribute [name]") | |
} | |
attrs.composition.defines.put(attrs.name, body) | |
} | |
} |
Composition contains a simple map:
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
class Composition { | |
Map defines = new HashMap() | |
} |
Example
The view
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<ui:composition template="/table"> | |
<ui:define composition="${it}" name="toolbar"> | |
[Toolbar content] | |
</ui:define> | |
<ui:define composition="${it}" name="table"> | |
[Table content] | |
</ui:define> | |
</ui:composition> |
The "table" template
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<div> | |
${toolbar()} | |
</div> | |
<div> | |
${table()} | |
</div> |
Conclusion
Easy!This taglib can replace Sitemesh layout however Sitemesh provides convention over configuration for layouts and Sitemesh is in Java and therefore much faster than Groovy [1].
UI composition pattern is more generic and leverage template layout and template reusing.
[1] Mean response time for 50 concurrent thread :
benchSitemesh 0.019751053s
benchComposition 0.027618479s
You can annotate defines map in Composition class with @Delegate and you should be able to access it directly from composition:
ReplyDeleteout << g.render(template: attrs.template, model: composition)
attrs.composition.put(attrs.name, body)
or
attrs.composition[attrs.name] = body
anyway this could lead to a little delay in executions, I didn't try it
Thanks for your advice :)
ReplyDeleteUseful advice :)
ReplyDelete