New Features of ZK 2.4

From Documentation
DocumentationSmall Talks2007JulyNew Features of ZK 2.4
New Features of ZK 2.4

Author
Tom M. Yeh and Henri Chen, Potix Corporation
Date
July 6, 2007
Version


In this article, we'll introduce you the most exciting new additions to ZK 2.4.


Load-on-Demand without Writing Java Codes

For better performance, it is common to defer the creation of a portion of a page, until it becomes visible. For example, we could create the list of combo items only when the list is dropped down as shown in the following code snippet.

//ZK 2.3 or ealier
<combobox id="combo" onOpen="prepare()"/>
<zscript>
void prepare() {
  if (event.isOpen() && combo.getItemCount() == 0) {
	combo.appendItem("Simple and Rich");
	combo.appendItem("Cool!");
	combo.appendItem("Ajax and RIA");
  }
}
</zscript>


ZK 2.4 introduces a new attribute called fulfill. By specifying when to create the child components in the fulfill attribute, you can implement the load-on-demand without writing any Java codes. For example, the above code snippet can be rewritten with fulfill as shown below:

//ZK 2.4 or later
<combobox fulfill="onOpen">
  <comboitem label="Simple and Rich"/>
  <comboitem label="Cool!"/>
  <comboitem label="Ajax and RIA"/>
</combobox>


If the creation of the child components depends on the event targeted for another component, you can specify the identifier in fulfill, as shown below.

<tabbox>
  <tabs>
	<tab label="Preload" selected="true"/>
	<tab id="tab2" label="OnDemand"/>
  </tabs>
  <tabpanels>
	<tabpanel>
This panel is pre-loaded since no fulfill specified
	</tabpanel>
	<tabpanel fulfill="tab2.onSelect">
This panel is loaded only tab2 receives the onSelect event
	</tabpanel>
  </tabpanels>
</tabbox>


Of course, the use of fulfill is limited only to the imagination.

<button id="btn" label="show" onClick="content.visible = true"/>
<div id="content" fulfill="btn.onClick">
  Any content created automaticall when btn is clicked
</div>

Thank Marcos de Sousa for his suggestion of this feature.


Use the Servlet Thread to Process Events

By default, ZK process an event in an independent thread called the event processing thread. Thus, the developer can suspend and resume the execution (of an event listener) at any time, without blocking the Servlet thread from sending back the responses to the browser.

However, it consumes more memory, especially if there are a lot suspended threads, and it may cause some challenge to integrate with other systems that storing information at the Servlet thread's local storage.

ZK 2.4 introduces a new option to let you disable the use of the event processing threads. In other words, you can force ZK to process events all in the Servlet threads.

To disable the use of the event processing threads, you have to specify the following content in WEB-INF/zk.xml.

<system-config>
  <disable-event-thread/>
</system-config>

There are some advantages, limations and workarounds about using the Servlet thread to process events. Remember to take a look at ZK Developer's Reference.

Thank Lin Li for his suggestion of this feature.

New and Simpler Way to Add Annotations

ZK 2.4 introduces an additional way to annotate properties: specify a value in the format of @{annot-name(attr-name=attr-value)} for the property to annotate. It is simpler to annotate and easier to read.

For example, the following code snippet declares an annotation rather than a value for the label property.

<listitem label="@{book(datasource='author',selected)}"/>


It is equivalent to

<listitem a:book="datasource='author',selected" label=""/>


If the annotation name is not specified, the name is assumed to be default. For example, the following code snippet annotates the label property with an annotation named default, and the annotation has one attribute whose name and value are value and selected.name, respectively.

<listitem label="@{selected.name}"/>


Use New Annotations with Data Binding

Taking advantage of the new way to annotate properties, the annotated data binding now is more intuitive, and clear.

Let us use an example to explain the improvement. The following is an example that annotate the data-binding info with the 'old' way.

<a:bind value="person.firstName; save-when:self.onChange; access:both"/>
<textbox id="firstName"/>
<a:bind value="person.lastName; save-when:self.onChange; access:both"/>
<textbox id="lastName"/>


And now let us rewrite it with the new way to annotate the data-binding information. ou can compare the difference yourselves.

<textbox id="firstName"
  value="@bind(person.firstName, save-when='self.onChange', access='both')"/>
<textbox id="lastName"
  value="@bind(person.lastName, save-when='self.onChange', access='both')"/>


In fact, the AnnotateDataBinder goes one step further. It now also accepts the "default" annotation name. That is, you do not specify the bind() annotation and it still works. The following example shows the simple way to specify data binding annotation and it is equivalent to the above example.

<textbox id="firstName"
  value="@{person.firstName, save-when='self.onChange', access='both'}"/>
<textbox id="lastName"
  value="@{person.lastName, save-when='self.onChange', access='both'}"/>


Note that since AnnotateDataBinder has setup the default "save-when", "load-when", and "access" info in the lang-addon.xml, you do not generally need to specify them explicitly. The following example is therefore equivalent to the above one with even simpler format.

<textbox id="firstName" value="@{person.firstName}"/>
<textbox id="lastName" value="@{person.lastName}"/>


Miscellaneous Enhancement

The Highlighted Window

ZK 2.4 introduces a new mode called highlighted to windows.

<window mode="highlighted"
title="Highlighted" border="normal"
width="200px" closable="true">
  Hello, Highlighted!
</window>


A highlighted window is similar to the overlapped windows, except the visual effect is the same as the modal windows. In other words, a highlighted window is positioned at the center of the browsers, and components not belonging to the highlighted window are disabled. However, it does not suspend the execution. Like the overlapped windows, the execution continues to the next statement once the mode is changed.

The highlighted window is aimed to substitute the modal window, if you prefer not to use or suspend the event processing thread.


Embedded Fileupload Component

ZK 2.4 introduces a new component called fileupload. The fileupload component is a component (not a modal dialog), so you can embed in any ZUML page you like. For example,

<image id="img"/>
Upload your hot shot:
<fileupload onUpload="img.setContent(event.media)"/>

Once the user uploads a file (or multiple files depending on how you configure fileupload), the onUploda event is sent to notify the application what files are uploaded.

Thank Godmar Back for his suggestion of this feature.


The onPiggyback Event

To prevent from blocking by a long operation, an application usually forks a working thread to process it. Due to the HTTP limiation, the application has to use a timer to check whether the result is ready periodically.

ZK 2.4 introduces an alternative way that you can piggyback the result to the client when the user, say, clicks a button.

To piggyback, all you need to do is to register an event listener for the onPiggyback event to one of the root components. Then, the listener will be invoked each time ZK Update Engine has processed the events. For example,

<window id="main" title="Working Thread3" onPiggyback="checkResult()">
  <zscript>
  List result = Collections.synchronizedList(new LinkedList());

  void checkResult() {
	while (!result.isEmpty())
	  main.appendChild(result.remove(0));
  }
  </zscript>
  <button label="Start Working Thread">
	<attribute name="onClick">
  timer.start();
  new test.WorkingThread2(desktop, result).start();
	</attribute>
  </button>
</window>

More Powerful org.zkoss.zul.ClientConstraint

Since 2.4, you can return a complet JavaScript code snippet in the getClientValidation method. For example, assume you have a JavaScript validation function as follows.

void myfunc(cmp, when, value) {
  var val = $real(cmp).value; //cmp is the component to validate
  //...
}


Then, you can return the following string in getClientValidation:

public String getClientValidation() {
  return "myfunc(#{self}, #{shipDate}, 234)";
}

where we assume the textbox has a custom field called shipDate.


Upgrade Notes

To simplify the implementation of event listener (org.zkoss.zk.ui.event.EventListener), the isAsap method is removed. An event listener is assumed to be ASAP (i.e., not deferable) unless org.zkoss.zk.ui.event.Deferrable is implemented.

In other words, if your old implementation of the isAsap method returns true, you simply remove it (since it is no longer part of EventListener). If it returns false, remove it and implements Deferrable in addition to EventListener:

public class DeferrableListener implements EventListener, Deferrable {
  public void onEvent(Event event) throws Exceptin {
	//process the event
  }
  public boolean isDeferrable() {
	return true; //It is deferrable, i.e., not ASAP
  }
}




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