Macro Component"

From Documentation
m
 
(7 intermediate revisions by 2 users not shown)
Line 7: Line 7:
 
On the other hand, we could implement a new component by using the others and composing them in a ZUML page. In other words, we could define a new component by expressing it in a ZUML page. It works like composition, macro expansion, or inline replacement.
 
On the other hand, we could implement a new component by using the others and composing them in a ZUML page. In other words, we could define a new component by expressing it in a ZUML page. It works like composition, macro expansion, or inline replacement.
  
For the sake of convenience, we call the first type of components as ''primitive components'', while the second type as ''macro components''. In this section we will get into more details on how to implement a macro component and how to use it.
+
For the sake of convenience, we call the first type of components ''primitive components'' and the second type ''macro components''. In this section we will get into more details on how to implement a macro component and how to use it.
  
 
{{ZKDevelopersReferenceHeadingToc}}
 
{{ZKDevelopersReferenceHeadingToc}}
Line 19: Line 19:
 
# Define (aka., Implement) a macro component in a ZUML page.
 
# Define (aka., Implement) a macro component in a ZUML page.
 
# Declare the macro component in the page or the whole application that is going to use the macro component.
 
# Declare the macro component in the page or the whole application that is going to use the macro component.
# Use the macro components. The use of a macro component is the same of using primitive components.
+
# Use the macro components. The use of a macro component is the same as using primitive components.
  
 
== Define Macro Component ==
 
== Define Macro Component ==
Line 25: Line 25:
 
The definition of a macro component is expressed in a ZUML page. In other words, the page is the template of the macro component. It is the same as any other ZUML pages as it does not require any special syntaxes at all. Furthermore, any ZUML page can be used as a macro component too.
 
The definition of a macro component is expressed in a ZUML page. In other words, the page is the template of the macro component. It is the same as any other ZUML pages as it does not require any special syntaxes at all. Furthermore, any ZUML page can be used as a macro component too.
  
For example, assume that we want to pack a label and a text box as a macro component. Then we could create page, say <tt>/WEB-INF/macros/username.zul</tt>, as follows.
+
For example, assume that we want to pack a label and a text box as a macro component. Then we could create a page, say <code>/WEB-INF/macros/username.zul</code>, as follows.
  
 
<source lang="xml" >
 
<source lang="xml" >
Line 32: Line 32:
 
</hlayout>
 
</hlayout>
 
</source>
 
</source>
 
It is done.
 
  
 
== Declare Macro Component ==
 
== Declare Macro Component ==
Line 43: Line 41:
 
</source>
 
</source>
  
As shown, we have to declare the component's name (the <tt>name</tt> attribute) and the URI of the page defining the macro component (the <tt>macroURI</tt> attribute).
+
As shown, we have to declare the component's name (the <code>name</code> attribute) and the URI of the page defining the macro component (the <code>macroURI</code> attribute).
  
 
If you prefer to make a macro component available to all pages, you could add the component definition to the so-called language addon and add it to [[ZK Configuration Reference/zk.xml/The language-config Element|WEB-INF/zk.xml]].
 
If you prefer to make a macro component available to all pages, you could add the component definition to the so-called language addon and add it to [[ZK Configuration Reference/zk.xml/The language-config Element|WEB-INF/zk.xml]].
Line 49: Line 47:
 
== Use Macro Component ==
 
== Use Macro Component ==
  
Using a macro component in a ZUML page is the same as the use of any other components. There is no difference at all
+
Using a macro component in a ZUML page is the same as the use of any other components. There is no difference at all.
  
 
<source lang="xml" >
 
<source lang="xml" >
Line 68: Line 66:
 
</source>
 
</source>
  
All these properties specified are stored in a map that is then passed to the template (aka., the macro definition; <tt>macroURI</tt>) via a variable called <tt>arg</tt>. Then, from the template, you could access these properties by the use of EL expressions as shown below:
+
All these properties specified are stored in a map that is then passed to the template (aka., the macro definition; <code>macroURI</code>) via a variable called <code>arg</code>. Then, from the template, you could access these properties by the use of EL expressions as shown below:
  
<source lang="xml" high="2">
+
<source lang="xml" highlight="2">
 
<hlayout>
 
<hlayout>
 
${arg.label}: <textbox value="${arg.who}"/>
 
${arg.label}: <textbox value="${arg.who}"/>
Line 78: Line 76:
 
== arg.includer ==
 
== arg.includer ==
  
In addition to properties (aka., attributes), a property called <tt>arg.includer</tt> is always passed. It refers the macro component itself. With this, we could reference it to other information such as parent:
+
In addition to properties (aka., attributes), a property called <code>arg.includer</code> is always passed. It refers to the macro component itself. With this, we could reference other information such as its parent:
  
 
<source lang="xml">
 
<source lang="xml">
Line 84: Line 82:
 
</source>
 
</source>
  
Notice that <tt>arg.includer</tt> is different from the so-called inline macros. The inline macros are special macro components and used for inline expansion. For more information please refer to [[ZK Developer's Reference/UI Composing/Macro Component/Inline Macros|Inline Macros]] section.
+
Notice that <code>arg.includer</code> is different from the so-called inline macros. The inline macros are special macro components and used for inline expansion. For more information please refer to [[ZK Developer's Reference/UI Composing/Macro Component/Inline Macros|Inline Macros]] section.
  
 
== Pass Initial Properties ==
 
== Pass Initial Properties ==
Line 114: Line 112:
 
# Looks up the component definition (<javadoc>org.zkoss.zk.ui.metainfo.ComponentDefinition</javadoc>) with the use of <javadoc method="getComponentDefinition(java.lang.String, boolean)">org.zkoss.zk.ui.Page</javadoc>.
 
# Looks up the component definition (<javadoc>org.zkoss.zk.ui.metainfo.ComponentDefinition</javadoc>) with the use of <javadoc method="getComponentDefinition(java.lang.String, boolean)">org.zkoss.zk.ui.Page</javadoc>.
 
# Invokes <javadoc method="newInstance(org.zkoss.zk.ui.Page, java.lang.String)">org.zkoss.zk.ui.metainfo.ComponentDefinition</javadoc> to instantiate the component.
 
# Invokes <javadoc method="newInstance(org.zkoss.zk.ui.Page, java.lang.String)">org.zkoss.zk.ui.metainfo.ComponentDefinition</javadoc> to instantiate the component.
# Invokes <javadoc method="setParent(org.zkoss.zk.ui.Component)">org.zkoss.zk.ui.Component</javadoc> to attach the macro to a parent, if necessary
+
# Invokes <javadoc method="setParent(org.zkoss.zk.ui.Component)">org.zkoss.zk.ui.Component</javadoc> to attach the macro to a parent, if necessary.
 
# Invokes <javadoc method="applyProperties()">org.zkoss.zk.ui.Component</javadoc> to apply the initial properties defined in the component definition.
 
# Invokes <javadoc method="applyProperties()">org.zkoss.zk.ui.Component</javadoc> to apply the initial properties defined in the component definition.
 
# Invokes <javadoc method="setDynamicProperty(java.lang.String, java.lang.Object)">org.zkoss.zk.ui.ext.DynamicPropertied</javadoc> to assign any properties you want.
 
# Invokes <javadoc method="setDynamicProperty(java.lang.String, java.lang.Object)">org.zkoss.zk.ui.ext.DynamicPropertied</javadoc> to assign any properties you want.
Line 130: Line 128:
 
</source>
 
</source>
  
It is a bit tedious. If you implement you own custom Java class (instead of <javadoc>org.zkoss.zk.ui.HtmlMacroComponent</javadoc>), it is simpler. For example,
+
It is a bit tedious. If you implement your own custom Java class (instead of <javadoc>org.zkoss.zk.ui.HtmlMacroComponent</javadoc>), it will be simpler. For example,
  
 
<source lang="Java">
 
<source lang="Java">
Line 142: Line 140:
 
== Change Template at Runtime ==
 
== Change Template at Runtime ==
  
You could change the template dynamically by use of <javadoc method="setMacroURI(java.lang.String)">org.zkoss.zk.ui.HtmlMacroComponent</javadoc>. For example,
+
You could change the template dynamically by the use of <javadoc method="setMacroURI(java.lang.String)">org.zkoss.zk.ui.HtmlMacroComponent</javadoc>. For example,
  
 
<source lang="xml" >
 
<source lang="xml" >
Line 149: Line 147:
 
</source>
 
</source>
  
If the macro component was instantiated, all of its children will be removed first, and then the new template will be appled (so-called recreation).
+
If the macro component was instantiated, all of its children will be removed first, and then the new template will be applied (so-called recreation).
 +
 
  
=Version History=
 
{{LastUpdated}}
 
{| border='1px' | width="100%"
 
! Version !! Date !! Content
 
|-
 
| &nbsp;
 
| &nbsp;
 
| &nbsp;
 
|}
 
  
 
{{ZKDevelopersReferencePageFooter}}
 
{{ZKDevelopersReferencePageFooter}}

Latest revision as of 06:20, 26 January 2024

There are two ways to implement a component. One is to implement a component in a Java class, extending from other component or one of the skeletal implementations with an optional JavaScript class. It is flexible and, technically, is also able to implement any functionality you want. For more information please refer to ZK Component Development Essentials.

On the other hand, we could implement a new component by using the others and composing them in a ZUML page. In other words, we could define a new component by expressing it in a ZUML page. It works like composition, macro expansion, or inline replacement.

For the sake of convenience, we call the first type of components primitive components and the second type macro components. In this section we will get into more details on how to implement a macro component and how to use it.



There is a similar concept called composite components. Unlike macros, you could derive from any component but you have to do the loading of ZUML manually. For more information please refer to the Composite Component section.

Definition, Declaration and Use

It is straightforward to apply macro components to an application:

  1. Define (aka., Implement) a macro component in a ZUML page.
  2. Declare the macro component in the page or the whole application that is going to use the macro component.
  3. Use the macro components. The use of a macro component is the same as using primitive components.

Define Macro Component

The definition of a macro component is expressed in a ZUML page. In other words, the page is the template of the macro component. It is the same as any other ZUML pages as it does not require any special syntaxes at all. Furthermore, any ZUML page can be used as a macro component too.

For example, assume that we want to pack a label and a text box as a macro component. Then we could create a page, say /WEB-INF/macros/username.zul, as follows.

<hlayout>
	Username: <textbox/>
</hlayout>

Declare Macro Component

Before using a macro component, you have to declare it first. It is straightforward to use component directives. For example, we could add the first line to the page that is going to use the username macro component:

<?component name="username" macroURI="/WEB-INF/macros/username.zul"?>

As shown, we have to declare the component's name (the name attribute) and the URI of the page defining the macro component (the macroURI attribute).

If you prefer to make a macro component available to all pages, you could add the component definition to the so-called language addon and add it to WEB-INF/zk.xml.

Use Macro Component

Using a macro component in a ZUML page is the same as the use of any other components. There is no difference at all.

<window>
	<username/>
</window>

Pass Properties to Macro Component

Like an ordinary component, you can specify properties (a.k.a., attributes) when using a macro component. For example,

<?component name="username" macroURI="/WEB-INF/macros/username.zul"?>
<window>
	<username who="John" label="Username"/>
</window>

All these properties specified are stored in a map that is then passed to the template (aka., the macro definition; macroURI) via a variable called arg. Then, from the template, you could access these properties by the use of EL expressions as shown below:

<hlayout>
	${arg.label}: <textbox value="${arg.who}"/>
</hlayout>

arg.includer

In addition to properties (aka., attributes), a property called arg.includer is always passed. It refers to the macro component itself. With this, we could reference other information such as its parent:

${arg.includer.parent}

Notice that arg.includer is different from the so-called inline macros. The inline macros are special macro components and used for inline expansion. For more information please refer to Inline Macros section.

Pass Initial Properties

Sometimes it is helpful to pass a list of initial properties that will be used to initialize a component when it is instantiated. It can be done easily as follows.

<?component name="mycomp" macroURI="/macros/mycomp.zul"
   myprop="myval" another="anotherval"?>

Therefore,

<mycomp/>

is equivalent to

<mycomp myprop="myval1" another="anotherval"/>

Control Macro in Java

Instantiate Macro in Java

To instantiate a macro component in Java, you could do the followings.

  1. Looks up the component definition (ComponentDefinition) with the use of Page.getComponentDefinition(String, boolean).
  2. Invokes ComponentDefinition.newInstance(Page, String) to instantiate the component.
  3. Invokes Component.setParent(Component) to attach the macro to a parent, if necessary.
  4. Invokes Component.applyProperties() to apply the initial properties defined in the component definition.
  5. Invokes DynamicPropertied.setDynamicProperty(String, Object) to assign any properties you want.
  6. Finally, invokes AfterCompose.afterCompose() to create components defined in the template

For example,

HtmlMacroComponent ua = (HtmlMacroComponent)
    page.getComponentDefinition("username", false).newInstance(page, null);
ua.setParent(wnd);
ua.applyProperties(); //apply properties defined in the component definition
ua.setDynamicProperty("who", "Joe");
ua.afterCompose(); //then the ZUML page is loaded and child components are created

It is a bit tedious. If you implement your own custom Java class (instead of HtmlMacroComponent), it will be simpler. For example,

Username ua = new Username();
ua.setParent(wnd);
ua.setWho("Joe");

Please refer to the Implement Custom Java Class section for details.

Change Template at Runtime

You could change the template dynamically by the use of HtmlMacroComponent.setMacroURI(String). For example,

<username id="ua"/>
<button onClick="ua.setMacroURI(&quot;another.zul&quot;)"/>

If the macro component was instantiated, all of its children will be removed first, and then the new template will be applied (so-called recreation).




Last Update : 2024/01/26

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