Saturday, April 14, 2012

ZK Datebox with Custom Server Side Parser


This post is about use the server-side custom parser with ZK Datebox,
tested with ZK 5.0.8.

How it works

Process flow:
1. User input some value and blur the input node of datebox

2. At this moment, the client side widget store the parsed value, send the inputed value to server side with 'onCustomParse' event.
We also set the busy state at client side to prevent any operation while parsing.

3. Server receive the 'onCustomParse' event and try to parse the value inputed by the user.

4. Two possible result,
4.A The server parse the value without any problem, and update the value to client side by Datebox#setValue.
4.B The server can not parse the value, ask the client reset to the original parsed value.

Finally clear the busy state.

The Program

package test.custom.component.datebox;

import java.util.Date;

import org.zkoss.zk.ui.event.Event;
import org.zkoss.zk.ui.event.Events;
import org.zkoss.zul.Datebox;

 * The Custom Datebox that can apply the service side custom date parser
public class CustomParserDatebox extends Datebox {

    private static final long serialVersionUID = 3683801858115113682L;
    static {
        // listen to the "onCustomParse" event
        addClientEvent(CustomParserDatebox.class, "onCustomParse", CE_IMPORTANT|CE_DUPLICATE_IGNORE);
    // override
    // the 'service' method is used to process the component's event from client side
    public void service( request, boolean everError) {
        final String cmd = request.getCommand();
        if (cmd.equals("onCustomParse")) {  // the 'onCustomParse' event
            String value = (String)request.getData().get("value");
            // assume we have the custom parser that
            // only parse the value '1' and '2'
            if ("1".equals(value)) { // parse value to date
                setValue(new Date(System.currentTimeMillis()));
                smartUpdate("backToOriginal", "clear");
            } else if ("2".equals(value)) { // parse value to date
                setValue(new Date(System.currentTimeMillis() - (1000L * 60 * 60 * 24 * 365)));
                smartUpdate("backToOriginal", "clear");
            else // can not parse, use original client side value
                smartUpdate("backToOriginal", "reset");
            Events.postEvent(new Event("onCustomParse", this, null));
        } else 
            super.service(request, everError);


<zk xmlns:w="client">
    <div style="margin: 20px;">
        <!-- The datebox that use the custom comopnent at server side
             Note that the 'onCustomParse=""' is required for
             listen to onCustomParse event -->
        <datebox lenient="true"
            <attribute w:name="doBlur_">
                function (evt) {
                    // store the user input
                    var userInput = this.$n('real').value;
                    // do original doBlur_
                    // store the client side parsed value
                    this._oriParsedValue = this.$n('real').value;
                    // tmp set the old value to input
                    this.$n('real').value = userInput;
                    // ask a custom parse from server
                    // the parsed value will be updated by setValue at server side
          'onCustomParse', {value: userInput});
                    // show busy to prevent any action when parse date
                    zAu.cmd0.showBusy(null, 'Busy, parsing...');
                    // show client side parsed value in label valO, can be removed
                    jq('$valO')[0].innerHTML = this._oriParsedValue;
            <attribute w:name="setBackToOriginal">
                // called when the server side parse is finished,
                // clear the stored client side parsed value if
                // custom parser parse the value without any problem
                // if the parse failed at server side,
                // reset input value with the original client side parsed value
                function (v) {
                    // reset to original value as need then clear it
                    if (this._oriParsedValue) {
                        if (v == 'reset') {
                            this.$n('real').value = this._oriParsedValue;
                            // clear valN label, can be removed
                            jq('$valN')[0].innerHTML = "";
                        } else { // the else fragment can be removed
                            // show client side parsed value in label valN
                            jq('$valN')[0].innerHTML = this.$n('real').value;
                        this._oriParsedValue = null;
                    // clear the busy state
        <div height="25px"></div>
        the client side parsed value: <label id="valO" />
        <div height="25px"></div>
        the value parsed by custom parser: <label id="valN" />

The Result

See the demo flash at

Thie files are available at github:

full project


demo movie (click 'View Raw' to download)


No comments:

Post a Comment