Include
Include
Employment/Purpose
The include component is used to include the output generated by another servlet. The servlet could be anything including JSF, JSP and even another ZUML page.
<window title="include demo" border="normal" width="300px">
Hello, World!
<include src="/userguide/misc/includedHello.zul" />
<include src="/html/frag.html?some=any" />
<include src="mypage" argument="${anyValue}" other="${anotherValue}" />
</window>
Like all other properties, you could dynamically change the src attribute to include the output from a different servlet at the run time.
If the included output is another ZUML, developers are allowed to access components in the included page as if they are part of the containing page.
If the include component is used to include a ZUML page, the included page will become part of the desktop. However, the included page is not visible until the request is processed completely. In other words, it is visible only in the following events, triggered by user or timer.
The reason is that the include component includes a page as late as the Rendering phase. On the other hand, zscript takes place at the Component Creation phase, and onCreate takes place at the Event Processing Phase. They both execute before the inclusion.
Example
<window title="include demo" border="normal" width="300px">
Hello, World!
<include src="/userguide/misc/includedHello.zul" />
<include src="/html/frag.html?some=any" />
<include src="mypage" argument="${anyValue}" other="${anotherValue}" />
</window>
Modes
There are two ways to include another ZUML document: instant and defer. It is controlled by the property called mode (Include.setMode(String)). By default, it is auto, i.e., the real mode is decided automatically as described below.
Auto
The auto mode (default) decides the mode based the page to include. If the page (Include.setSrc(String)) is ended with the extension named .zul or .zhtml, the <ttinstant mode is assumed. Otherwise, the defer mode is assumed. If it is not the case (such as your ZUML page's extension is not any of them), you could specify the mode explicitly.
Notice that if a query string is specified, the defer
mode is assumed, too, since the instance mode does not support the query string.
The code below demonstrates how to use the auto mode:
<window title="demo" border="normal">
<include mode="auto" src="another.zul" />
</window>
Instant
The instant mode allows pages to be created immediately using the Execution.createComponents(String, Component, Map) function, meaning that they are instantly accessible to the user and therefore no confusion or problems arise due to the initialization order.
The code below demonstrates how to use the instant mode:
<window title="demo" border="normal">
<include mode="instant" src="include.zul" />
</window>
Pass Values to the Included Page
you can pass values through Include.setDynamicProperty(String, Object). Unlike the defer mode, the query string is not supported in the instant mode.
For example:
<include src="mypage" some="something" another="${expr}"/>
Then, you could retrieve the values by use the arg object as described in the Load ZUML in Java section.
In the defer mode, the values have to be retrieved by the requestScope object.
Defer
The defer mode allows the page to be included by servlet container (the include method of javax.servlet.RequestDispatcher) in the render phase (i.e., after all components are created). The page can be any servlet; not limited to a ZUML page. The code below demonstrates how to use the defer mode:
<window title="demo" border="normal">
<include mode="defer" src="include.zul" />
</window>
Pass Values to the Included Page
There are two ways to pass values to the included page in the defer
mode. First, you can pass them with the query string.
<include src="mypage?some=something"/>
Then, in the included page, you can access them with Execution.getParameter(String) or the javax.servlet.ServletRequest interface. In EL expressions (of the included page), you can use the param object or the paramValues object to access them.
${param.some}
Notice that you can only pass String-typed values with the query string. Alternatively, we can pass any kind of values with the so-called dynamic properties by use of Include.setDynamicProperty(String, Object) or, in ZUL, a dynamic property as follows:
<include src="mypage" some="something" another="${expr}"/>
With the dynamic properties, you can pass non-String-typed values. In the included page, you can access them with Execution.getAttribute(String) or the javax.servlet.ServletRequest interface. In EL expressions (of the included page), you can use the requestScope object to access them.
${requestScope.some}
Refresh Inner Pages Only
First, use include component and specifies the src attribute to include whatever page you want (ZK, JSP, JSF or whatever) inside a ZK page. Second, you can dynamically change it by changing the src attribute. e.g. The following code would change the inner page from hello.zul to byebye.zul when an end user press the Bye! button.
<include id="inner" src="hello.zul"/>
<button label="Bye!" onClick='inner.src = "byebye.zul"'/>
If you simply want to reload the same page(and not to change to another page), you have to set the src attribute to null first; then set the src attribute back to what it was. Because ZK optimizes operations, set same value to the same attribute would be deemed doing nothing. e.g. The following code would refresh the hello.zul page when an end user press the Reload button.
<include id="inner" src="hello.zul"/>
<button id="reload" label="Reload" onClick="String tmp=inner.src; inner.src=null; inner.src=tmp;"/>
Another way is to invalidate the "include" element:
<include id="inner" src="hello.zul"/>
<button id="reload" label="Reload" onClick="inner.invalidate();"/>
Include the Same Page Twice
With the include component, you could include any page multiple times as follows.
<include src="/mypage.zul"/>
<include src="/mypage.zul"/>
However, if you want to access the component inside of them, you have to assign a unique identifier of the page being included. Here is what you can do.
<include src="/mypage.zul?pageId=first"/>
<include src="/mypage.zul?pageId=second"/>
In additions, in the page being include, i.e., mypage.zul in this example, you have to write
<?page id="${param.pageId}"?>
Then, you could access their component.
Path.getComponent('//first/textbox/');
Path.getComponent('//second/textbox/');
Notice that components are created as late as the Rendering phase, so you could access them only in the event listener for the following events:
<window>
<zscript><![CDATA[
/**
* in a real application we would use something like
* List iterateOverMe = sessionScope.get("listToRender");
*/
String[][] iterateOverMe = {
{ "99", "Fred Flintstone" },
{ "8", "Wilma Flintstone" },
{ "65", "Barney Rubble" },
{ "32", "Betty Rubble" }
};
]]></zscript>
<tabbox mold="accordion">
<tabs>
<!-- more realisticly my iterateOverMe would be a List of
pojos so that I can write ${each.label} -->
<tab forEach="${iterateOverMe}" label="${each[1]}" />
</tabs>
<tabpanels>
<!-- more realisticly my iterateOverMe would be a List of
pojos so that I can write ${each.id} -->
<tabpanel forEach="${iterateOverMe}">
<include src="/render-item.zul?pageId=${each[0]}" />
</tabpanel>
</tabpanels>
</tabbox>
</window>
In that page we pull in search-item.zul once for each object the search results list and we give the included page a pageId that is the identifier of the item that is to be rendered i.e. 99,8,65,32. Within render-item.zul:
<?page id="${param.pageId}"?>
<zscript>
// Here we have to use param.pageId to locate the object that we will render
Object itemToRender = ... // use param.pageId as the identifer to locate specific object to render at this time
</zscript>
<vbox>
<button label="${itemToRender.label}" />
</vbox>
In this file is included four separate times and param.pageId differs each time i.e. 99,8,65,32. Each time the page is called we use the param.pageId to find the business item to be rended.
Backward Compatibility
For versions prior to 5.0, the defer mode is the default. If you prefer to keep using the defer mode, you could specify a library property called org.zkoss.zul.include.mode as follows.
<library-property>
<name>org.zkoss.zul.include.mode</name>
<value>defer</value>
</library-property>
Supported Events
None | None |
- Inherited Supported Events: XulElement
Supported Children
*NONE
Use Cases
Version | Description | Example Location |
---|---|---|
Version History
Version | Date | Content |
---|---|---|
5.0.0 | January 2010 | The mode is default to auto (rather than defer). You could configure the default mode to defer by specifying a library property called org.zkoss.zul.include.mode in WEB-INF/zk.xml. |