Add and Remove Event Listeners by Program
This documentation is for an older version of ZK. For the latest one, please click here.
There are two ways to add event listeners by program.
Declare a Member
When overriding a component by use of your own class, you could declare a member function to be an event listener as follows.
In a ZUML page, you declare the use
attribute to specify what class you want to use instead of the default one. As illustrated below, it asks ZK to use the MyWindow
class instead of Window[1].
<window use="MyWindow">
...
</window>
Then, you implement MyWindow.java
by extending from the default class as follows.
public class MyWindow extends org.zkoss.zul.Window {
public void onOK() { //add an event listener
...//handles the onOK event (sent when ENTER is pressed)
}
}
If you want to retrieve more information about the event, you could declare as follows.
public void onOK(org.zkoss.zk.ui.event.KeyEvent event) {
...
}
or
public void onOK(org.zkoss.zk.ui.event.Event event) {
...
}
Different events might be associated with different event objects.
Add and Remove Event Listeners Dynamically
Developers could use the addEventListener
and removeEventListener
methods of the Component interface to dynamically add or remove an event listener. As illustrated below, the event listener to be added dynamically must implement the EventListener interface.
void init(Component comp) {
...
comp.addEventListener("onClick", new MyListener());
...
}
class MyListener implements org.zkoss.zk.ui.event.EventListener {
public void onEvent(Event event) throws UiException {
...//processing the event
}
}
Deferrable Event Listeners
By default, events are sent to the server when it is fired at the client. However, many event listeners are just used to maintain the status at the server, rather than providing visual response to the user. In other words, the events for these listeners have no need to be sent immediately. Rather, they shall be sent at once to minimize the traffic between the client and the server, and then to improve the server's performance. For the sake of the description convenience, we call them the deferrable event listeners.
To make an event listener deferrable, you have to implement the Deferrable interface (with EventListener
) and return true for the isDeferrable
method as follows.
public class DeferrableListener implements EventListener, Deferrable {
private boolean _modified;
public void onEvent(Event event) {
_modified = true;
}
public boolean isDeferrable() {
return true;
}
}
When an event is fired at the client (e.g., the user selects a list item), ZK won't send the event if no event listener is registered for it or only deferrable listeners are registered. instead, the event is queued at the client.
On the hand, if at least one non-deferrable listener is registered, the event are sent immediately with all queued events to the server at once. No event is lost and the arriving order is preserved.
Tip: Use the deferrable listeners for maintaining the server status, while the non-deferrable listeners for providing the visual responses for the user.
Add and Remove Event Listeners to Pages Dynamically
Developers could add event listeners to a page (Page) dynamically. Once added, all events of the specified name the are sent to any components of the specified page will be sent to the listener.
All page-level event listeners are non-ASAP. In other words, the isArap
method is ignored.
A typical example is to use a page-level event listener to maintain the modification flag as follows.
public class ModificationListener implements EventListener, Deferrable {
private final Window _owner;
private final Page _page;
private boolean _modified;
public ModificationListener(Window owner) {
//Note: we have to remember the page because unregister might
//be called after the owner is detached
_owner = owner;
_page = owner.getPage();
_page.addEventListener("onChange", this);
_page.addEventListener("onSelect", this);
_page.addEventListener("onCheck", this);
}
/** Called to unregister the event listener.
*/
public void unregister() {
_page.removeEventListener("onChange", this);
_page.removeEventListener("onSelect", this);
_page.removeEventListener("onCheck", this);
}
/** Returns whether the modified flag is set.
*/
public boolean isModified() {
return _modified;
}
//-- EventListener --//
public void onEvent(Event event) throws UiException {
_modified = true;
}
//-- Deferrable --//
public boolean isDeferrable() {
return true;
}
}
Note: Whether to implement the Deferrable
interface is optional in this example, because the page's event listeners are always assumed to be deferrable, no matter Deferrable
is implemented or not.
The Invocation Sequence
The sequence of invoking event listeners is as follows. Let us assume the onClick
event is received.
- Invoke event listeners for the
onClick
event one-by-one that are added to the targeting component, if the listeners also implement the Express interface. The first added, the first called. - Invoke the script specified in the
onClick
attribute of the targeting component, if any. - Invoke event listeners for the
onClick
event one-by-one that are added to the targeting component, if the listeners don't implement the Express interface. The first added, the first called. - Invoke the
onClick
member method of the targeting component, if any. - Invoke event listeners for the
onClick
event one-by-one that are added to the page that the targeting component belongs. The first added, the first called.
The Express interface is a decorative interface used to alter the invocation priority of an event listener. Notice that it is meaningless if the event listener is added to pages, instead of components.
Abort the Invocation Sequence
You could abort the calling sequence by calling the stopPropagation
method in the Event class. Once one of the event listeners invokes this method, all following event listeners are ignored.
Notes
- ↑ The default class is defined in lang.xml embedded in zul.jar.