Handling events on ZK macro components
One of the great features of ZK is the possibility to create a new component based only on other existing components using the declarative language ZUML - the same you've been using in you zul files. Those are called Macro Components. The beauty of macro components is that it's very easy to make a new one and hence avoid code duplication on your pages.
Talk about how to implement a macro component isn't the scope of this post, so I suggest you to read the documentation before continue reading.
We'll work on a very simple macro component. But, don't hesitate when you need to make a very complex one. Our macro component is this: WEB-INF/mymacro.zul
<hbox>
<label id="myLabel" value="Click the button"/>
<button id="myButton" label="The Button"/>
</hbox>Now that you already knows what is and how to make a macro component, let's start talking about what you may think it'll work but actually it doesn't.
Automatically Forward Event Doesn't Work
The standard way to register events on ZK's component, using MVC, is to use the "autowire" feature of GenericForwardComposer. Like this:
WEB-INF/index.zul
<?xml version="1.0" encoding="UTF-8"?>
<zk>
<window apply="com.felipecypriano.IndexComposer">
<label id="lblOutside"/>
<button id="btnOutside" label="Not In Macro"/>
</window>
</zk>src/com/felipecypriano/IndexComposer.java
package com.felipecypriano;
import org.zkoss.zk.ui.util.GenericForwardComposer;
import org.zkoss.zul.Label;
public class IndexComposer extends GenericForwardComposer {
private Label lblOutside;
public void onClick$btnOutside() {
lblOutside.setValue("Button 'not in macro' clicked");
}
}The button 'btnOutside' belongs to the window component and therefore its composer can automatically access and configure btnOutside events. When the Composer is initializing it detects the method onClick$btnOutside() and sets this method as a 'btnOutside' onClick event listener, in other words when the component is clicked this method is executed.
Knowing this we can think that add an event to 'myButton', which belongs to 'mymacro', is pretty much the same. Don't we? Let's add the macro in the index.zul and create a new method to handle onClick event of 'myButton':
WEB-INF/index.zul
<?xml version="1.0" encoding="UTF-8"?>
<?component name="mymacro" macroURI="/mymacro.zul" ?>
<zk>
<window apply="com.felipecypriano.IndexComposer">
<label id="lblOutside"/>
<button id="btnOutside" label="Not In Macro"/>
<separator bar="true"/>
<mymacro/>
</window>
</zk>Just before <zk> tag is the macro component definition (line 2), this directive tells to ZK where is the file that contains the component - macroURI="/mymacro.zul" - and what's the tag name we'll use - name="mymacro" - to reference our component (line 8).
Adding the onClick event on 'myButton' cannot be done by just adding this method to IndexComposer:
src/com/felipecypriano/IndexComposer.java
public void onClick$myButton() {
lblOutside.setValue("Button 'myButton' clicked");
}So, if this doesn't work what should I do?
