Include"

From Documentation
m (correct highlight (via JWB))
 
(55 intermediate revisions by 7 users not shown)
Line 9: Line 9:
  
 
= Employment/Purpose =
 
= Employment/Purpose =
The <tt>include</tt> component is used to include the output generated by another servlet. The servlet could be anything including JSF, JSP and even another ZUML page.
+
The <code>include</code> component is used to include the output generated by another servlet. The servlet could be anything including JSF, JSP and even another ZUML page.
  
 
<source lang="xml" >
 
<source lang="xml" >
Line 20: Line 20:
 
</source>
 
</source>
  
Like all other properties, you could dynamically change the <tt>src</tt> attribute to include the output from a different servlet at the run time.
+
Like all other properties, you could dynamically change the <code>src</code> attribute to include the output from a different servlet at 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 included output is from another ZUML, this allows developers to access components in the included page as if they are part of the containing page.
  
If the <tt>include</tt> 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.
+
If the <code>include</code> 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.
 
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.
Line 38: Line 38:
 
</source>
 
</source>
  
=Pass Values to the Included Page=
+
=Modes=
There are two ways to pass values to the included page. First, you can pass them with the query string.
+
There are two ways to include another ZUML document: <code>instant</code> and <code>defer</code>. It is controlled by the property called mode (<javadoc method="setMode(java.lang.String)">org.zkoss.zul.Include</javadoc>). By default, it is <code>auto</code>, i.e., the real mode is decided automatically as described below.
 +
Notice that the included file should not contain &lt;html> tag.
  
<source lang="xml" >
+
==Auto==
<include src="mypage?some=something"/>
 
</source>
 
  
Then, in the included page, you can access them with the <tt>getParameter</tt> method of the <tt>Execution</tt> interface or the <tt>ServletRequest</tt> interface. In EL expressions (of the included page), you can use the <tt>param</tt> variable to access them. However, you can only pass String-typed values with the query string.
+
The <code>auto</code> mode (default) decides the mode based the page to include.  If the page (<javadoc method="setSrc(java.lang.String)">org.zkoss.zul.Include</javadoc>) is ended with the extension named <code>.zul</code>, <code>.zhtml</code>, <code>.html</code>, or <code>.xhtml</code>, the <code>instant</code> mode is assumed. Otherwise, the <code>defer</code> 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.
  
${param.some}
+
Notice that if a query string is specified, the <code>defer</code> mode is assumed, too, since the <code>instant</code> mode does not support the query string (#1).
 
+
<blockquote>
Alternatively, we can pass any kind of values with the so-called dynamic properties by use of the <tt>setDynamicProperty</tt> method or, in ZUL, a dynamic property as follows:
+
----
 +
That means , the following sample is using <code>defer</code> mode so the ${param.test} in header.zul is working .
  
 
<source lang="xml" >
 
<source lang="xml" >
<include src="mypage" some="something" another="${expr}"/>
+
  <include src="header.zul?test=5" />                          <!-- default mode is auto -->
 
</source>
 
</source>
  
With the dynamic properties, you can pass non-String-typed values. In the included page, you can access them with the <tt>getAttribute</tt> method of the <tt>Execution</tt> interface or the <tt>ServletRequest</tt> interface. In EL expressions (of the included page), you can use the <tt>requestScope</tt> variable to access them.
+
but the following sample is using <code>instant</code> mode , so the ${param.test} in the header.zul is not working.
  
${requestScope.some}
+
<source lang="xml" >
 +
  <include mode="instant" src="header.zul?test=5" />      <!-- set the instant mode explicitly -->
 +
</source>
  
=Modes=
+
If you have no any query string in src and it's ended with ".zul" , the include will be <code>instant</code> mode by default.
There are two ways to include another ZUML document: <tt>instant</tt> and <tt>defer</tt>. It is controlled by the property called mode (<javadoc method="setMode(java.lang.String)">org.zkoss.zul.Include</javadoc>). By default, it is <tt>auto</tt>, i.e., the real mode is decided automatically as described below.
+
<source lang="xml" >
 
+
  <include src="header.zul" />                               <!-- default mode is auto -->
<blockquote>
+
</source>
 
----
 
----
''Backward Compatibility:'' For versions prior to 5.0, the <tt>defer</tt> mode is the default. If you prefer to keep using the defer mode, you could specify a library property called [[ZK Configuration Reference/zk.xml/The Library Properties/org.zkoss.zul.include.mode|org.zkoss.zul.include.mode]].
 
 
</blockquote>
 
</blockquote>
==Auto==
 
  
The ''auto'' mode selects which mode is most suited for the inclusion type. If the inclusion is a ZUL file then the ''instant'' mode will be used and if not the ''defer'' mode will be.
 
  
 
The code below demonstrates how to use the ''auto'' mode:
 
The code below demonstrates how to use the ''auto'' mode:
Line 74: Line 73:
 
<source lang="xml">
 
<source lang="xml">
 
<window title="demo" border="normal">
 
<window title="demo" border="normal">
<include mode="auto" src="include.zul" />
+
<include mode="auto" src="another.zul" />
 
</window>
 
</window>
 
</source>
 
</source>
Line 80: Line 79:
 
==Instant==
 
==Instant==
  
The ''instant'' mode allows pages to be created immediately using the <javadoc method="createComponents(java.lang.String, org.zkoss.zk.ui.Component, java.util.Map)">org.zkoss.zk.ui.Execution</javadoc> function, meaning that they are instantly accessible to the user and therefore no confusion or problems arise due to the initialization order.
+
In the <code>instant</code> mode, the <code>include</code> component loads the page by the use of <javadoc method="createComponents(java.lang.String, org.zkoss.zk.ui.Component, java.util.Map)" type="interface">org.zkoss.zk.ui.Execution</javadoc>. It means that the components defined in the included page are instantiated ''instantly'' and added as children of the <code>include</code> component.
 +
 
 +
Unlike the <code>defer</code> mode, no additional <javadoc type="interface">org.zkoss.zk.ui.Page</javadoc> instance is created.
  
 
The code below demonstrates how to use the ''instant'' mode:
 
The code below demonstrates how to use the ''instant'' mode:
Line 89: Line 90:
 
</window>
 
</window>
 
</source>
 
</source>
 +
 +
Notice the <code>include</code> component itself is [[ZK Developer's Reference/UI Composing/ID Space|a ID space owner]], so there is no issue of ID conflicts. But, it also means you have to use <javadoc>org.zkoss.zk.ui.Path</javadoc> or other techniques to retrieve the child components.
 +
 +
===Pass Values to the Included Page===
 +
you can pass values through <javadoc method="setDynamicProperty(java.lang.String, java.lang.Object)">org.zkoss.zul.Include</javadoc>. Unlike the ''defer'' mode, the query string is not supported in the ''instant'' mode.
 +
 +
For example:
 +
 +
<source lang="xml" >
 +
<include src="mypage" some="something" another="${expr}"/>
 +
</source>
 +
 +
Then, you could retrieve the values by use [[ZUML Reference/EL Expressions/Implicit Objects/arg|the arg object]] as described in [[ZK Developer's Reference/UI Composing/ZUML/Load ZUML in Java|the Load ZUML in Java section]].
 +
 +
<blockquote>
 +
----
 +
In the <code>defer</code> mode, the values have to be retrieved by [[ZUML Reference/EL Expressions/Implicit Objects/requestScope|the requestScope object]].
 +
----
 +
Unfortunately there is [https://sourceforge.net/tracker/?func=detail&aid=3142583&group_id=152762&atid=785191 a bug] in 5.0.5, so it won't work unless you use 5.0.6 or later.
 +
</blockquote>
  
 
==Defer==
 
==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.
+
In the <code>defer</code> mode, the <code>include</code> component includes the page by going through the Servlet container(the include method of javax.servlet.RequestDispatcher). Thus, it is OK to include any kind of pages, not limited to ZUML documents.
The code below demonstrates how to use the ''defer'' mode:
 
  
 
<source lang="xml">
 
<source lang="xml">
Line 101: Line 121:
 
</source>
 
</source>
  
=== Refresh Inner Pages Only ===
+
===Differences to the Instant Mode===
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.
+
Here is a list of differences between the <code>defer</code> and <code>instant</code> modes if a ZUML document is included (directly or indirectly going through another, say, JSP page) to contain the components defined in the included ZUML document.
 +
 
 +
* In the <code>defer</code> mode, an instance of <javadoc type="interface">org.zkoss.zk.ui.Page</javadoc> will be created.
 +
* In the <code>defer</code> mode, the instantiated components become the root of the <javadoc type="interface">org.zkoss.zk.ui.Page</javadoc> instance. The <code>include</code> component itself has no child component at all.
 +
* In the <code>defer</code> mode, the page is included when the <code>include</code> component is rendered. Thus, the <javadoc type="interface">org.zkoss.zk.ui.Page</javadoc> instance (and its content) is not available when loading the ZUML document that the <code>include</code> component belongs to. It means you cannot access any of its content until receiving an AU request from the client.
 +
 
 +
===Pass Values to the Included Page===
 +
There are two ways to pass values to the included page in the <code>defer</code> mode. First, you can pass them with the query string.
 +
 
 +
<source lang="xml" >
 +
<include mode="defer" src="mypage?some=something"/>
 +
</source>
 +
 
 +
Then, in the included page, you can access them with <javadoc method="getParameter(java.lang.String)" type="interface">org.zkoss.zk.ui.Execution</javadoc> or the <code>javax.servlet.ServletRequest</code> interface. In EL expressions (of the included page), you can use [[ZUML Reference/EL Expressions/Implicit Objects/param|the <code>param</code> object]] or [[ZUML Reference/EL Expressions/Implicit Objects/paramValues|the paramValues object]] to access them.
  
 
<source lang="xml">
 
<source lang="xml">
<include id="inner" src="hello.zul"/>
+
${param.some}
<button label="Bye!" onClick='inner.src = "byebye.zul"'/>
 
 
</source>
 
</source>
  
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.
+
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 <javadoc method="setDynamicProperty(java.lang.String, java.lang.Object)">org.zkoss.zul.Include</javadoc> or, in ZUL, a dynamic property as follows:
  
<source lang="xml">
+
<source lang="xml" >
<include id="inner" src="hello.zul"/>
+
<include mode="defer" src="mypage" some="something" another="${expr}"/>
<button id="reload" label="Reload" onClick="String tmp=inner.src; inner.src=null; inner.src=tmp;"/>
 
 
</source>
 
</source>
  
Another way is to invalidate the "include" element:
+
With the dynamic properties, you can pass non-String-typed values. In the included page, you can access them with <javadoc method="getAttribute(java.lang.String)" type="interface">org.zkoss.zk.ui.Execution</javadoc> or the <code>javax.servlet.ServletRequest</code> interface. In EL expressions (of the included page), you can use [[ZUML Reference/EL Expressions/Implicit Objects/requestScope|the requestScope object]] to access them.
 +
 
 
<source lang="xml">
 
<source lang="xml">
<include id="inner" src="hello.zul"/>
+
${requestScope.some}
<button id="reload" label="Reload" onClick="inner.invalidate();"/>
 
 
</source>
 
</source>
  
 
=== Include the Same Page Twice ===
 
=== Include the Same Page Twice ===
  
With the include component, you could include any page multiple times as follows.
+
With the include component, you could include any pages multiple times no matter it is in the <code>instant</code> or <code>defer</code> mode. For example,
  
 
<source lang="xml">
 
<source lang="xml">
Line 131: Line 162:
 
</source>
 
</source>
  
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.
+
However, if you are using the <code>defer</code> mode and 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.
  
 
<source lang="xml">
 
<source lang="xml">
<include src="/mypage.zul?pageId=first"/>
+
<include mode="defer" src="/mypage.zul?pageId=first"/>
<include src="/mypage.zul?pageId=second"/>
+
<include mode="defer" src="/mypage.zul?pageId=second"/>
 
</source>
 
</source>
  
In additions, in the page being include, i.e., mypage.zul in this example, you have to write
+
In additions, in the page being include, i.e., <code>mypage.zul</code> in this example, you have to write
  
 
<source lang="xml">
 
<source lang="xml">
Line 144: Line 175:
 
</source>
 
</source>
  
Then, you could access their component.
+
Then, you could access their component by the use of <javadoc>org.zkoss.zk.ui.Path</javadoc> as follows.
  
 
<source lang="xml">
 
<source lang="xml">
Line 151: Line 182:
 
</source>
 
</source>
  
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:
+
Notice that, in the <code>defer</code> mode, components are created as late as rendering the <code>include</code> component, so you could access them only in the event listener serving AU requests (aka., Ajax).
 +
 
 +
=== Include Non-ZUML Pages ===
  
<source lang="java">
+
If the included page is not ZUML (such as a HTML fragment), the content is generated directly, so they might be evaluated before widgets are rendered. Technically it is OK. However, if the included page embeds some JavaScript code that depends on widgets, it might run as you expected. For example, assume we have the includer and included page as follows:
<window>
+
 
<zscript><![CDATA[
+
<source lang="xml">
/**
+
<!-- includer -->
* in a real application we would use something like
+
<window id="main">
*        List iterateOverMe = sessionScope.get("listToRender");
+
  <include src="frag.html"/>
*/
 
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>
 
</window>
 
</source>
 
</source>
  
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:
+
<source lang="xml">
 +
<!-- included -->
 +
<script>zk.log(jq("$main"));</script>
 +
</source>
 +
 
 +
Then, <code>jq("$main")</code> will resolve nothing (an empty array) because its content is evaluated first.
  
<source lang="xml">
+
There are two solutions to make it evaluate later:
<?page id="${param.pageId}"?>
+
 
<zscript>
+
#Use <javadoc method="afterMount(_global_.Function, int)" directory="jsdoc">_global_.zk</javadoc> in the included page
// Here we have to use param.pageId to locate the object that we will render
+
#Or, specify this custom attribute to defer the rendering in the includer.
Object itemToRender = ... // use param.pageId as the identifer to locate specific object to render at this time
+
 
</zscript>
+
'''Use zk.afterMount() in the included page'''
<vbox>
+
 
<button label="${itemToRender.label}" />
+
First, you could use <javadoc method="afterMount(_global_.Function, int)" directory="jsdoc">_global_.zk</javadoc> to defer the evaluation as follows in the included page:
</vbox>
+
 
 +
<source lang="html">
 +
<!-- the included non-ZUML page -->
 +
<script>
 +
zk.afterMount(function () {
 +
    zk.log(jq("$main"));
 +
    ...//handle widgets:
 +
});
 +
</script>
 
</source>
 
</source>
  
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.
+
'''Use the org.zkoss.zul.include.html.defer attribute'''
 +
 
 +
{{versionSince|5.0.7}}
  
==Making defer your default mode==
+
Alternatively, you could specify a custom attribute called <code>the org.zkoss.zul.include.html.defer</code> in the <javadoc>org.zkoss.zul.Include</javadoc> component (rather than using <javadoc method="afterMount(_global_.Function, int)" directory="jsdoc">_global_.zk</javadoc> in the included component):
  
By default, the auto mode is assumed, but if you want to use it as same as ZK 3.x version, you can set the defer mode as default by including a library variable in your zk.xml configuration file.  
+
<source lang="xml" highlight="3">
 +
<!-- the includee -->
 +
<include src="included.html">
 +
    <custom-attributes org.zkoss.zul.include.html.defer="true"/>
 +
</include>
 +
</source>
  
The XML below demonstrates how to do this:
+
==Backward Compatibility==
  
 +
For versions prior to 5.0, the <code>defer</code> mode is the default. If you prefer to keep using the defer mode, you could specify a library property called [[ZK Configuration Reference/zk.xml/The Library Properties/org.zkoss.zul.include.mode|org.zkoss.zul.include.mode]] as follows.
 
<source lang="xml">
 
<source lang="xml">
 
<library-property>
 
<library-property>
        <name>org.zkoss.zul.include.mode</name>
+
    <name>org.zkoss.zul.include.mode</name>
<value>defer</value>
+
    <value>defer</value>
 
</library-property>
 
</library-property>
 
</source>
 
</source>
 +
 +
= Refresh Included Pages =
 +
First, use the <code>include</code> component with either the <code>instant</code> or <code>defer</code> mode to include whatever page you want (ZUML, JSP, JSF or whatever) inside a ZK document. Second, you can dynamically change it by changing the <code>src</code> property (<javadoc method="setSrc(java.lang.String)">org.zkoss.zul.Include</javadoc>.
 +
 +
For example, the following code would change the included page from <code>hello.zul</code> to <code>byebye.zul</code>, when an end user press the <code>Bye!</code> button.
 +
 +
<source lang="xml">
 +
<include id="inner" src="hello.zul"/>
 +
<button label="Bye!" onClick='inner.src = "byebye.zul"'/>
 +
</source>
 +
 +
If you want to ''reload'' the same page (and not to change to another page), you have to set the <code>src</code> property to null first; then set it  back to what it was. Because ZK optimizes operations, setting the same value to the same property would be deemed to do nothing.
 +
 +
For example, the following code would refresh the <code>hello.zul</code> page when an end user press the <code>Reload</code> button.
 +
 +
<source lang="xml">
 +
<include id="inner" src="hello.zul"/>
 +
<button id="reload" label="Reload" onClick="String tmp=inner.src; inner.src=null; inner.src=tmp;"/>
 +
</source>
 +
 +
Another way to reload is to invalidate the "include" component by use of <javadoc method="invalidate()" type="interface">org.zkoss.zk.ui.Component</javadoc> as follows.
 +
 +
<source lang="xml">
 +
<include id="inner" src="hello.zul"/>
 +
<button id="reload" label="Reload" onClick="inner.invalidate();"/>
 +
</source>
 +
 +
Notice that <javadoc method="invalidate()" type="interface">org.zkoss.zk.ui.Component</javadoc> will cause the included page to be reloaded in both the <code>instance</code> and <code>defer</code> mode.
 +
 +
= Access Components Inside =
 +
Since <code>include</code> creates ID space, to access components inside it , please refer to [[ZK_Developer%27s_Reference/UI_Composing/ID_Space#Find_Component_Manually]]
 +
 +
=Progressing for Slow Pages=
 +
If an included page takes too long to load, you could specify true to the <code>progressing</code> property (<javadoc method="setProgressing(boolean)">org.zkoss.zul.Include</javadoc>). Thus, the included page won't load in the same HTTP request, so the including page will be ready to the client as soon as possible.
 +
 +
<source lang="xml">
 +
<include page="slow.zul" progressing="true"/>
 +
</source>
 +
 +
ZK Client Engine will show a busy message to indicate that the page is not ready yet, and this prevents users from accessing it. Then, the real loading of the included page will then take place later. Though the end user still cannot access the page, the feed back is much better (with a ''semi-ready'' page than totally blank).
 +
 +
This feature is actually done by the use of the so-called [[ZK Developer's Reference/Event Handling/Event Firing|echo event]]. For more information, please refer to the [[ZK Developer's Reference/UI Patterns/Long Operations/Use Echo Events|Long Operations: Use Echo Events]] section.
 +
 +
This feature cannot be used with the <code>instant</code> mode. If the <code>auto</code> mode is used (default), it switches to the defer mode automatically.
 +
 +
=Custom Attributes=
 +
 +
== org.zkoss.zul.include.html.defer ==
 +
[default: false]
 +
[inherit: true]<ref>The custom attribute could be specified in this component, or any of its ancestor. In addition, it could be specified as [[ZK Configuration Reference/zk.xml/The library-property Element|a library property]] to enable or disable it for the whole application.</ref>
 +
{{versionSince|5.0.7}}
 +
 +
It specifies whether to defer the rendering of the included non-ZUML page, until all widgets are instantiated and rendered at the client. By default, if the included page is not ZUML (i.e., HTML fragment), the content is generated directly, and they might be evaluated before widgets are rendered (depending on the browser and the complexity of a page).
 +
 +
For more information, please refer to the [[#Include Non-ZUML Pages]] section.
 +
 +
<blockquote>
 +
----
 +
<references/>
 +
</blockquote>
  
 
=Supported Events=
 
=Supported Events=
  
{| border="1" | width="100%"
+
{| class='wikitable' | width="100%"
 
! <center>Name</center>
 
! <center>Name</center>
 
! <center>Event Type</center>
 
! <center>Event Type</center>
Line 229: Line 321:
 
=Use Cases=
 
=Use Cases=
  
{| border='1px' | width="100%"
+
{| class='wikitable' | width="100%"
 
! Version !! Description !! Example Location
 
! Version !! Description !! Example Location
 
|-
 
|-
Line 239: Line 331:
 
=Version History=
 
=Version History=
 
{{LastUpdated}}
 
{{LastUpdated}}
{| border='1px' | width="100%"
+
{| class='wikitable' | width="100%"
 
! Version !! Date !! Content
 
! Version !! Date !! Content
 
|-
 
|-
| &nbsp;
+
| 5.0.0
| &nbsp;
+
| January 2010
| &nbsp;
+
| The mode is default to <code>auto</code> (rather than <code>defer</code>). You could configure the default mode to defer by specifying a library property called [[ZK Configuration Reference/zk.xml/The Library Properties/org.zkoss.zul.include.mode|org.zkoss.zul.include.mode]] in <code>WEB-INF/zk.xml</code>.
 +
|-
 +
| 5.0.7
 +
| April 2011
 +
| The custom attribute called <code>org.zkoss.zul.include.html.defer</code> was introduced to defer the rendering of a non-ZUML page (such as HTML fragment) until all widgets are instantiated and rendered at the client.
 
|}
 
|}
  
 
{{ZKComponentReferencePageFooter}}
 
{{ZKComponentReferencePageFooter}}

Latest revision as of 09:07, 18 January 2022

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 run time.

If the included output is from another ZUML, this allows developers 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. Notice that the included file should not contain <html> tag.

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, .zhtml, .html, or .xhtml, the instant 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 instant mode does not support the query string (#1).


That means , the following sample is using defer mode so the ${param.test} in header.zul is working .

   <include src="header.zul?test=5" />                          <!-- default mode is auto -->

but the following sample is using instant mode , so the ${param.test} in the header.zul is not working.

   <include mode="instant" src="header.zul?test=5" />       <!-- set the instant mode explicitly -->

If you have no any query string in src and it's ended with ".zul" , the include will be instant mode by default.

   <include src="header.zul" />                                <!-- default mode is auto -->


The code below demonstrates how to use the auto mode:

<window title="demo" border="normal">
	<include mode="auto" src="another.zul" />
</window>

Instant

In the instant mode, the include component loads the page by the use of Execution.createComponents(String, Component, Map). It means that the components defined in the included page are instantiated instantly and added as children of the include component.

Unlike the defer mode, no additional Page instance is created.

The code below demonstrates how to use the instant mode:

<window title="demo" border="normal">
	<include mode="instant" src="include.zul" />
</window>

Notice the include component itself is a ID space owner, so there is no issue of ID conflicts. But, it also means you have to use Path or other techniques to retrieve the child components.

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.


Unfortunately there is a bug in 5.0.5, so it won't work unless you use 5.0.6 or later.

Defer

In the defer mode, the include component includes the page by going through the Servlet container(the include method of javax.servlet.RequestDispatcher). Thus, it is OK to include any kind of pages, not limited to ZUML documents.

<window title="demo" border="normal">
	<include mode="defer" src="include.zul" />
</window>

Differences to the Instant Mode

Here is a list of differences between the defer and instant modes if a ZUML document is included (directly or indirectly going through another, say, JSP page) to contain the components defined in the included ZUML document.

  • In the defer mode, an instance of Page will be created.
  • In the defer mode, the instantiated components become the root of the Page instance. The include component itself has no child component at all.
  • In the defer mode, the page is included when the include component is rendered. Thus, the Page instance (and its content) is not available when loading the ZUML document that the include component belongs to. It means you cannot access any of its content until receiving an AU request from the client.

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 mode="defer" 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 mode="defer" 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}

Include the Same Page Twice

With the include component, you could include any pages multiple times no matter it is in the instant or defer mode. For example,

<include src="/mypage.zul"/>
<include src="/mypage.zul"/>

However, if you are using the defer mode and 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 mode="defer" src="/mypage.zul?pageId=first"/>
<include mode="defer" 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 by the use of Path as follows.

Path.getComponent('//first/textbox/'); 
Path.getComponent('//second/textbox/');

Notice that, in the defer mode, components are created as late as rendering the include component, so you could access them only in the event listener serving AU requests (aka., Ajax).

Include Non-ZUML Pages

If the included page is not ZUML (such as a HTML fragment), the content is generated directly, so they might be evaluated before widgets are rendered. Technically it is OK. However, if the included page embeds some JavaScript code that depends on widgets, it might run as you expected. For example, assume we have the includer and included page as follows:

<!-- includer -->
<window id="main">
  <include src="frag.html"/>
</window>
<!-- included -->
<script>zk.log(jq("$main"));</script>

Then, jq("$main") will resolve nothing (an empty array) because its content is evaluated first.

There are two solutions to make it evaluate later:

  1. Use zk.afterMount(Function, int) in the included page
  2. Or, specify this custom attribute to defer the rendering in the includer.

Use zk.afterMount() in the included page

First, you could use zk.afterMount(Function, int) to defer the evaluation as follows in the included page:

<!-- the included non-ZUML page -->
<script>
zk.afterMount(function () {
    zk.log(jq("$main"));
    ...//handle widgets:
});
</script>

Use the org.zkoss.zul.include.html.defer attribute

Since 5.0.7

Alternatively, you could specify a custom attribute called the org.zkoss.zul.include.html.defer in the Include component (rather than using zk.afterMount(Function, int) in the included component):

<!-- the includee -->
<include src="included.html">
    <custom-attributes org.zkoss.zul.include.html.defer="true"/>
</include>

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>

Refresh Included Pages

First, use the include component with either the instant or defer mode to include whatever page you want (ZUML, JSP, JSF or whatever) inside a ZK document. Second, you can dynamically change it by changing the src property (Include.setSrc(String).

For example, the following code would change the included 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 want to reload the same page (and not to change to another page), you have to set the src property to null first; then set it back to what it was. Because ZK optimizes operations, setting the same value to the same property would be deemed to do nothing.

For example, 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 to reload is to invalidate the "include" component by use of Component.invalidate() as follows.

<include id="inner" src="hello.zul"/>
<button id="reload" label="Reload" onClick="inner.invalidate();"/>

Notice that Component.invalidate() will cause the included page to be reloaded in both the instance and defer mode.

Access Components Inside

Since include creates ID space, to access components inside it , please refer to ZK_Developer's_Reference/UI_Composing/ID_Space#Find_Component_Manually

Progressing for Slow Pages

If an included page takes too long to load, you could specify true to the progressing property (Include.setProgressing(boolean)). Thus, the included page won't load in the same HTTP request, so the including page will be ready to the client as soon as possible.

<include page="slow.zul" progressing="true"/>

ZK Client Engine will show a busy message to indicate that the page is not ready yet, and this prevents users from accessing it. Then, the real loading of the included page will then take place later. Though the end user still cannot access the page, the feed back is much better (with a semi-ready page than totally blank).

This feature is actually done by the use of the so-called echo event. For more information, please refer to the Long Operations: Use Echo Events section.

This feature cannot be used with the instant mode. If the auto mode is used (default), it switches to the defer mode automatically.

Custom Attributes

org.zkoss.zul.include.html.defer

[default: false]
[inherit: true][1]

Since 5.0.7

It specifies whether to defer the rendering of the included non-ZUML page, until all widgets are instantiated and rendered at the client. By default, if the included page is not ZUML (i.e., HTML fragment), the content is generated directly, and they might be evaluated before widgets are rendered (depending on the browser and the complexity of a page).

For more information, please refer to the #Include Non-ZUML Pages section.


  1. The custom attribute could be specified in this component, or any of its ancestor. In addition, it could be specified as a library property to enable or disable it for the whole application.

Supported Events

Name
Event Type
None None

Supported Children

*NONE

Use Cases

Version Description Example Location
     

Version History

Last Update : 2022/01/18


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.
5.0.7 April 2011 The custom attribute called org.zkoss.zul.include.html.defer was introduced to defer the rendering of a non-ZUML page (such as HTML fragment) until all widgets are instantiated and rendered at the client.



Last Update : 2022/01/18

Copyright © Potix Corporation. This article is licensed under GNU Free Documentation License.