Composition
Composition is one of the built-in templating implementations. The concept is simple:
- Define a template (a ZUML document representing a complete UI)
- Define a ZUML document that contains a collections of fragments that a template might reference
Notice that the user shall visit the ZUML document with a collection of fragments rather than the template document.
The advantage of Composition is that you don't need additional configuration file.
Note: the composition doesn't support to mix up with ZUML and ZHTML language, that is, if you define a ZHTML template as the HTML content that contains Html and Body tags, you cannot use that template in a ZUML page.
Defines a Template
A template document is a ZUML document that defines how to assemble the fragments. For example,
<!-- /WEB-INF/layout/template.zul -->
<vbox>
<hbox self="@insert(content)"/>
<hbox self="@insert(detail)"/>
</vbox>
As shown, the anchor (i.e., the component that a fragment will insert as children) is defined by specify an annotation as @insert(name)
. Then, when Composition is applied to a ZUML document with a collections of fragments, the matched fragment will become the child of the annotated component (such as hbox
in the above example).
Define Fragments
To apply a template to a ZUML document that an user visits, you have to defined a collection of fragments that a template might use, and then specify Composition as one of the initiators of the document:
<!-- foo/index.zul -->
<?init class="org.zkoss.zk.ui.util.Composition"
arg0="/WEB-INF/layout/template.zul"?>
<zk>
<window self="@define(content)" title="window1" width="100px"/>
<window self="@define(content)" title="window2" width="200px"/>
<grid self="@define(detail)" width="300px" height="100px"/>
</zk>
As shown, a fragment is defined by specifying an annotation as self="@define(name)"
. Furthermore, the template is specified in the init directive.
Then, when the user visits this page (foo/index.zul
in the above example), Composition will do:
- Load the template, and render it as the root components of this page(
foo/index.zul
) - Move the fragments specified in this page to become the children of the anchor component with the same annotation name
Thus, here is the result
<vbox>
<hbox>
<window title="window1" width="100px"/>
<window title="window2" width="200px"/>
</hbox>
<hbox>
<grid width="300px" height="100px"/>
</hbox>
</vbox>
Multiple Templates
You could apply multiple templates to a single page too:
<?init class="org.zkoss.zk.ui.util.Composition"
arg0="/WEB-INF/layout/template0.zul" arg1="/WEB-INF/layout/template1.zul"?>
The templates specified in arg0 and arg1 (etc.) will be loaded and rendered one-by-one.
Grouping Fragments into Separated Files
In a complex templating environment, it might not be appropriate to put fragments in the target page (e.g., foo/index.zul
in the above example), since you might want to use the same collection of fragments in several target pages. It can be easily by use of the include component as follows.
<!-- foo/index.zul -->
<?init class="org.zkoss.zk.ui.util.Composition"
arg0="/WEB-INF/layout/template.zul"?>
<include src="/WEB-INF/layout/fragments.zul"/>
Then, you could group fragments into one or multiple individual ZUL documents, such as
<!-- /WEB-INF/layout/fragments.zul -->
<zk>
<window self="@define(content)" title="window1" width="100px"/>
<window self="@define(content)" title="window2" width="200px"/>
<grid self="@define(detail)" width="300px" height="100px"/>
</zk>
Positioning
If you want to use Composition inside any of containers (like Div,Window,Tabbox) , you have to use the include component and set its mode 'defer' :
Note: You have to specify Composition as of the initiators of the 'fragments')
<!-- foo/index.zul -->
<window title="This is a window" border="normal">
<include src="/WEB-INF/layout/fragments.zul" mode="defer" />
</window>
<!-- /WEB-INF/layout/fragments.zul -->
<?init class="org.zkoss.zk.ui.util.Composition" arg0="/WEB-INF/layout/template.zul"?>
<zk>
<window self="@define(content)" title="window1" width="100px"/>
<window self="@define(content)" title="window2" width="200px"/>
<grid self="@define(detail)" width="300px" height="100px"/>
</zk>
Version History
Version | Date | Content |
---|---|---|