Implement Custom Java Class
Overview
As described in the earlier sections, a macro component is instantiated to represent a regular macro. By default, HtmlMacroComponent is assumed (and instantiated). However, you provide a custom Java class to provide a better API to simplify the access and to encapsulate the implementation.
Implement Custom Java Class for Macro
The implementation is straightforward. First, the custom Java class for macro components must extend from HtmlMacroComponent. Second, it shall invoke HtmlMacroComponent.compose() in the constructor[1], such that the template will be applied in the constructor.
For example, suppose we have a macro template as follows.
<hlayout>
Username: <textbox id="mc_who"/>
</hlayout>
Then, we could implement a Java class for it:
package foo;
import org.zkoss.zk.ui.HtmlMacroComponent;
import org.zkoss.zul.Textbox;
public class Username extends HtmlMacroComponent {
private Textbox mc_who; //will be wired when compose() is called
public Username() {
compose(); //fore the template to be applied
}
public String getWho() {
return mc_who.getValue();
}
public void setWho(String who) {
mc_who.setValue(who);
}
//public void onOK() {..} //you could add event listeners too
}
Notice that HtmlMacroComponent.compose() will wire fellows and event listener automatically, so we could access them directly (such as the mc_who
member). For more information, please refer to the Wire Variables and
Wire Event Listeners sections.
Also notice that the arg
variable is still available to the template so as to represent properties set by DynamicPropertied.setDynamicProperty(String, Object). However, it is pointless to use it if we provide all required setters.
- ↑ HtmlMacroComponent.compose() is available in 5.0.5. For 5.0.4 or earlier, please invoke HtmlMacroComponent.afterCompose() instead.
Declare Macro with Custom Java Class
To make ZK Loader know which custom Java class to use, we have to specify the class
attribute when declaring it in the component directives. For example,
<?component name="username" macroURI="/WEB-INF/macros/username.zul"
class="foo.Username"?>
Use Macro with Custom Java Class
In ZUML
The use of the macro component with a custom Java class in a ZUML page is the same as other macro components.
In Java
The main purpose of introducing a custom Java class is to simplify the use of a macro component in Java. For example, you could invoke a more meaningful setter, say, setWho, directly rather than DynamicPropertied.setDynamicProperty(String, Object). In addition, the instantiation could be as simple as follows:
Username ua = new Username();
ua.setParent(wnd);
ua.setWho("Joe");
Macro Component and ID Space
Like Window, HtmlMacroComponent also implements IdSpacce. It means a macro component (excluding inline macros) is a space owner. In other words, it is free to use whatever identifiers to identify components inside the template.
For example, assume we have a macro defined as follows.
<hlayout>
Username: <textbox id="who" value="${arg.who}"/>
</hlayout>
Then, the following codes work correctly.
<?component name="username" macroURI="/WEB-INF/macros/username.zul"?>
<zk>
<username/>
<button id="who"/> <!-- no conflict because it is in a different ID space -->
</zk>
However, the following codes don't work.
<?component name="username" macroURI="/WEB-INF/macros/username.zul"?>
<username id="who"/>
Why? Like any ID space owner, the macro component itself is in the same ID space with its child components. There are two alternative solutions:
1. Use a special prefix for the identifiers of child components of a macro component. For example, "mc_who" instead of "who".
<hlayout>
Username: <textbox id="mc_who" value="${arg.who}"/>
</hlayout>
2. Use the window component to create an additional ID space.
<window>
<hlayout>
Username: <textbox id="who" value="${arg.who}"/>
</hlayout>
</window>
The first solution is suggested, if applicable, due to the simplicity.
Version History
Version | Date | Content |
---|---|---|
5.0.5 | October, 2010 | HtmlMacroComponent.compose() was introduced. |