It is the component's job to communicate between the view and the handle, while the communication is transparent to the application developers.
The communication is kind of pitch-and-catch. It usually involves the view and the handle. In this section, we focus on the handle (the server side). The view (the client side) will be described in the later chapter.
There are three ways to send a response to the view (the client side): invalidates, smart updates and responses. An invalidate causes the whole view of the component to be redrawn. A smart update causes a particular attribute of the component's view to be changed. An AU response is a fully customizable response to manipulate the component's view.
public void invalidate();
When the invalidate method is called, the component is marked as dirty, and then the redraw method will be called to generate the whole view to client in the Rendering phase.
The typical use is to call invalidate(), when the invocation of a method changes the view.
public void setLabel(String label) {
if (!Objects8org.zkoss.lang.Objects.equals() compares if two objects equal (even both null)..equals(_label, label)) {
_label = label;
invalidate();
}
}
It is the simplest way to update the view since we don't need to write any JavaScript codes. The view is updated with the redrawn view automatically by ZK. However, if the component contains a lot of child components (such as a grid), it is costly to redraw the whole view (since it has to also redraw all child components). Thus, if the change is mirror, the performance will be better if you use smart updates or AU responses.
Note: ZK optimizes the invalidates before invoking the redraw method. For example, a component will be redrawn at most one time, even if it is invalidated multiple times, or its parent is invalidated, too.
public void smartUpdate(String attrName, String value);public void smartUpdate(String attrName, DeferredValue value);public void smartUpdate(String attrName, boolean value);public void smartUpdate(String attrName, int value);
A smart update is used to modify an attribute of the view. Unlike an invalidate, it won't cause the component to be redrawn.
public void setReadonly(boolean readonly) {
if (_readonly != readonly) {
_readonly = readonly;
smartUpdate("readOnly", _readonly);
}
}
By default, ZK Client Engine will update the attribute of the most outer DOM element (of the view) with the specified name. For example, assume the most outer DOM element of the above example is elem, it is equivalent to invoke the following JavaScript codes at the client:
elem.readOnly = _readonly;
ZK Client Engine is smart enough to invoke the correct method for updating a field. For example, elem.className for the class attribute, elem.setAttribute() for unrecognized attributes, and so on.
In additions, you can provide your own JavaScript codes to handle smart updates at the client, if you want to handle smart updates in a component-specific way.
Note: if both smart updates and invalidates are called against the same component, the smart updates will be ignored – after all, the whole view will be redrawn.
public void response(String key, AuResponse[8] response);
An AU response is the lowest-level response. You can fully customize it to do whatever you want.
However, you rarely need to use AU responses directly, since invalidates and smart updates can do almost everything you want. Remember you can provide your custom JavaScript codes to handle smart updates at the client. In other words, you can use smart updates to execute something at the client; not just modify an attribute.
Unlike smart updates, an AU responses are always sent to the client even if an invalidate is called against the same component. It is one of the reason we have to use AU responses for certain circumstances.
For example, let us say we want to implement the focus feature. Since we want to change the focus to a component even if it is invalidated, an AU response is the only choice.
public void focus() {response("focus", new AuFocus(this));}
where AuFocus is one of built-in AU responses extending from AuResponse with predefined functionality.
We say an AU response depends on a component, if it shall not be sent to the client when the component is removed. It is controlled by the depends argument of the constructor.
In most cases, an AU response depends on a component.
Note: Unlike smart updates, the AU response is sent to the client even if the component it depends is invalidated (until the component is removed).
There are a lot of built-in AU responses such as AuAlert, AuInvoke, AuPrint and so on in the org.zkoss.zk.au.out package. When you think you have to develop your own AU response, check Javadoc first if any of them fulfills your requirement.
AuInvoke and AuScript are AU response used to invoke the JavaScript codes at the client. AuInoke is used to invoke a JavaScript method depending on the component's type, while AuScript invokes a piece of codes regardless if it is part of a component's view.
public void play() {
response("play", new AuScript(this, "alert('Hi')"));
}
We discuss how to create your custom AU response in the later chapter, since it requires some JavaScript codes.
To notify what happens at the client, the view has to send an AU request (org.zkoss.zk.au.AuRequest) to the server. The AU request is processed by the so-called command. Whether to update the component and whether to post an event depends on how a command is implemented.
A command (org.zkoss.zk.au.Command) is used to process certain type of AU requests. When ZK Update Engine receives an AU request, it associates a command with it. Then, it invokes the process method of the command to process it. The processing, depending on the requirement, usually updates the content of the component and then posts an event to notify the application.
For example, the org.zkoss.zk.au.in.RemoveCommand command is registered to process all AU requests called remove. Thus, if an AU request called remove is received, the process method of RemoveCommand will be invoked. Here is how RemoveCommand is implemented:
public class RemoveCommand extends Command {
public RemoveCommand(String evtnm, int flags) {
super(evtnm, flags);
}
protected void process(AuRequest request) {
final Component comp = request.getComponent();
if (comp != null) comp.detach();
}
}
Note: ZK uses the same command instance for the same type of AU requests, so concurrent access of the command is possible.
See Also: Refer to the Process Request at the Server section in the next chapter for more details.
When a command processing a request, it might post one or several events. For example, InputCommand will post the onChange event as an instance of org.zkoss.zk.ui.event.InputEvent. The events are queued until all commands are processed. In other words, the events are processed by the application, after the components have been updated.
There is a common question for developing a component: shall I update the component's state in a command or in an event listener. In general, it is better to use event to notify the application only. And, it is better to update the component's state in a command. After all, the application might stop the event propagation at any time (Event.stopPropagation).
On the other hand, we can utilize the stop-propagation feature to allow the application to customize some behavior. For example, the list box sorts the list items in the onSort listener, such that the application can provide its own sorting by adding its own listener and stop the event propagation.