ZK: Examples

This article is a collection of small examples and code snippets that illustrates the use of the ZK framework. ZK is an open source project that enables rich user interfaces for Web applications.
This wiki page was started in year 2006, some of the contents may no longer apply. For latest updates and examples, please visit the following links

Thanks for your contributions.

Snippets from the demo

edit

A good starting point for seeing zk-code in action is the ZK Live Demo. The examples are visualized and editable in the demo, so you should try the demo first.

User contributed code snippets

edit

Snippets within zul-pages

edit

Grid: multi column sort


<window title="Sorting test">
    <zscript><![CDATA[
            class Comp implements Comparator {
                    private boolean _ascd;
                    private int _columnIndex;
                    
                    public Comp(boolean ascd, int columnIndex) {
                        _ascd = ascd;
                        _columnIndex = columnIndex;
                    }
                    
                    public int compare(Object o1, Object o2) {
                            String s1 = o1.getChildren().get(_columnIndex).getValue(),
                                   s2 = o2.getChildren().get(_columnIndex).getValue();
                            int v = s1.compareTo(s2);
                            return _ascd ? v: -v;
                    }
            }
            // Instances for first column
            Comp ascd1 = new Comp(true, 0);
            Comp dscd1 = new Comp(false, 0);
            // Instances for second column
            Comp ascd2 = new Comp(true, 1);
            Comp dscd2 = new Comp(false, 1);
    ]]></zscript>
    <grid id="gTest">
        <columns>
            <column id="gcColOne" label="Year" width="10%" sortAscending="&#36;{ascd1}" sortDescending="&#36;{dscd1}" />
            <column id="gcColTwo" label="Number" width="90%" sortAscending="&#36;{ascd2}" sortDescending="&#36;{dscd2}" />
        </columns>
        <rows id="gTestRows">
            <row><label value="2000" /><label value="8" /></row>
            <row><label value="2006" /><label value="1" /></row>
            <row><label value="2002" /><label value="7" /></row>
            <row><label value="2003" /><label value="2" /></row>
            <row><label value="2007" /><label value="6" /></row>
        </rows>
    </grid>
</window>

Listbox: multi-column sort and rendering of 'live' data

<window title="Livedata Sorting/Rendering Demo" border="normal">
    <zscript><![CDATA[

        /** Person. */
        public class Person {
            private String name;
            private String job;
            public Person(String name,String job) { this.name=name; this.job=job; }
            public String getName() { return this.name; }
            public String getJob() { return this.job; }
            public String toString() { return "Person[name:"+name+";job:"+job+"]"; }
        }

        /** MyModel. */
        public class MyModel extends ListModelList {
            public MyModel(List list) {
                super(list, true);
            }
            public void sort(Comparator cmpr, boolean ascending) {
                Collections.sort(getInnerList() , cmpr);
                fireEvent(org.zkoss.zul.event.ListDataEvent.CONTENTS_CHANGED, -1, -1);
            }
        }

        /** MyPersonRenderer for rendering a Person in the Listbox. */
        public class MyPersonRenderer implements ListitemRenderer {
            public void render(Listitem li, Object data) {
                Person p = (Person)data;
                new Listcell(p.getName()).setParent(li);
                new Listcell(p.getJob()).setParent(li);
            }
        }
        ListitemRenderer myPersonRenderer = new MyPersonRenderer();

        /** Comparators for Persons. */
        public class MyPersonComparator implements Comparator {
            private boolean ascending;
            private int columnIndex;
            public MyPersonComparator (boolean ascending, int columnIndex) {
                this.ascending = ascending;
                this.columnIndex = columnIndex;
            }
            public int compare(Object o1, Object o2) {
                System.out.println("MyPersonComparator : " + o1 + " vs " + o2);
                Person p1 = (Person )o1;
                Person p2 = (Person)o2;
                int v = 0;
                switch (columnIndex) {
                    case 0:
                        v = p1.getName().compareTo(p2.getName());
                        break;
                    case 1:
                        v = p1.getJob().compareTo(p2.getJob());
                        break;
                }
                return ascending ? v: -v;
            }
        }
        Comparator cmpName_A = new MyPersonComparator (true,0);
        Comparator cmpName_D = new MyPersonComparator (false,0);
        Comparator cmpJob_A = new MyPersonComparator (true,1);
        Comparator cmpJob_D = new MyPersonComparator (false,1);

        /** The ListModel data */
        java.util.List list = new java.util.ArrayList();
        list.add(new Person("Bruce Willis", "Actor"));
        list.add(new Person("Neil Armstrong", "Astronaut"));
        list.add(new Person("Robin Hood", "Outlaw"));
        list.add(new Person("Albert Einstein", "Scientist"));
        list.add(new Person("Dinglemouse", "Mouse"));
        list.add(new Person("William Shakespeare", "Playwright"));
        ListModel myModel = new MyModel(list);

    ]]></zscript>

    <listbox id="list" width="300px" rows="5">
        <attribute name="model" >${myModel}</attribute>
        <attribute name="itemRenderer" >${myPersonRenderer}</attribute>
        <listhead>
            <listheader label="Name" sortAscending="${cmpName_A}" sortDescending="${cmpName_D}"/>
            <listheader label="Job" sortAscending="${cmpJob_A}" sortDescending="${cmpJob_D}"/>
        </listhead>
    </listbox>

</window>

Clear combobox value

<window title="checkbox demo" border="normal">
	<combobox id="aa">
		<comboitem label="Simple and Rich"/>
		<comboitem label="Cool!"/>
		<comboitem label="Thumbs Up!"/>
	</combobox>
	<button label="clear combo" onClick="aa.value=&quot;&quot;"/>
</window>

Treeitem with onRightClick-event

<zk>
<listbox width="250px">
	<listhead sizable="true">
		<listheader label="name" sort="auto"/>
		<listheader label="gender" sort="auto"/>
	</listhead>
	<listitem id="li1">
		<listcell label="Mary"/>
		<listcell label="FEMALE"/>
	</listitem>
	<listitem id="li2">
		<listcell label="John"/>
		<listcell label="MALE"/>
	</listitem>
</listbox>
<zscript>
li1.addEventListener("onRightClick", new EventListener() {
  public boolean isAsap() {
    return true;
  }
  public void onEvent(Event e) {
    Messagebox.show("hi! Right click!");
  }
});
</zscript>
</zk>

Multi-language labels (internationalization)

'Important:' the following described files have to be in UTF-8-format or special characters like German umlauts will not be displayed correctly!

In the /WEB-INF-directory create the files according to your needs, f.i. one with the standard labels (this one is selected if no matching language files could be found), i3-labels.properties:

app.title=Standard entry for the label if no other language-file matches
app.title.setByJavaCode=Standard entry for the label set by java code if no other language-file matches
app.question.delete={
Do you really want to delete this item? (Standard)
If enclosed in curly brackets, you can also include multiline-messages...
}
app.question.confirm=Please confirm...

, one for user with German locale, i3-labels_de.properties:

app.title=Test für deutschen Label (German label)
app.title.setByJavaCode=Set by java code: Test für deutschen Label (German label)
app.question.delete={
Wirklich dieses Item löschen (Deutsch/German)?
Durch die Eingabe innerhalb von geschwungenen Klammern sind auch mehrzeilige Meldungen möglich.
}
app.question.confirm=Bitte bestätigen (de)...

, and finally one for users with German locale in Germany, i3-labels_de_DE.properties:

app.title=Test für deutschen Label in Deutschland (German label in Germany)
app.title.setByJavaCode=Set by java code: Test für deutschen Label in Deutschland (German label in Germany)
app.question.delete={
Wirklich dieses Item löschen (Deutsch in Deutschland/German in Germany)?
Durch die Eingabe innerhalb von geschwungenen Klammern sind auch mehrzeilige Meldungen möglich.
}
app.question.confirm=Bitte bestätigen (de_DE)...

If you want to change also the messages in the messageboxes you have to create special files in the directory /WEB-INF/classes/metainfo/mesg/ (at least on Tomcat; else in the /<classpath>/metainfo/mesg/). The name of the files depend on the message you want to overwrite/create a language dependent value. For a list of all available messages you can unzip the jar-files of zk with your favourite unpacker and look at the included metainfo/mesg/*.properties-files. F.i. to change the Messagebox.YES or Messagebox.NO values you have to create a file /WEB-INF/classes/metainfo/mesg/msgzul_de.properties (as the values are defined in the zul.jar) with the following content:

2220=Ja bitte
2221=Nein danke

The values before the =, f.i. 2220 for Messagebox.YES can be seen in the metainfo/mesg/msgzul.properties-file if you unzip the zul.jar-file. Some examples for the messageboxes:

#-=OK
2200=OK
#-=CANCEL
2201=Cancel
#-=YES
2220=Yes
#-=NO
2221=No
#-=RETRY
2230=Retry
#-=ABORT
2231=Abort
#-=IGNORE
2232=Ignore

Next is the zul-file, where the first label is hardcoded, the second one set with an el-expression and the third is set with java-code. If you click on the button, a messagebox is shown depending on your locale.

<?xml version="1.0" encoding="UTF-8"?>
<?taglib uri="/WEB-INF/tld/web/core.dsp.tld" prefix="c" ?>
<zk>
	<window onCreate="setLabel3()">
		<zscript>
			public setLabel3() {
				lbl3.setValue(org.zkoss.util.resource.Labels.getLabel("app.title.setByJavaCode"));
			}

                        public showMsgBox() {
                                Messagebox.show(org.zkoss.util.resource.Labels.getLabel("app.question.delete"), org.zkoss.util.resource.Labels.getLabel("app.question.confirm"), Messagebox.YES | Messagebox.NO, Messagebox.QUESTION);
                        }
		</zscript>
		<vbox>
			<label id="lbl1" value="Hard coded label" />
			<label id="lbl2" value="With el: ${c:l('app.title')}" />
			<label id="lbl3" value="Will be set by java class" />
                        <button id="btnMsg" label="Messagebox" onClick="showMsgBox()" />
		</vbox>
	</window>
</zk>

The taglib-tag is only needed if you want to use the el-expression. If you have many labels, you can also do the following within zscript (for shortening the getLabel-command):

import org.zkoss.util.resource.Labels;

public setLabel3() {
        lbl3.setValue(Labels.getLabel("app.title.setByJavaCode"));
}

Snippets within java-code

edit

Refresh (redraw) a component Every component has a redraw-method, so to refresh its appearance try the following.

// F.i. you have a button with id="btn"
java.io.StringWriter wr = new java.io.StringWriter();
btn.redraw(wr);

Selecting in a listbox via label

for(Iterator it = mylistbox.getItems().iterator(); it.hasNext();) {
  Listitem li = (Listitem) it.next();
  if ("b".equals(li.getLabel()) {
    li.setSelected(true);
    break;
  }
}

Set language-dependent label value

((Label) Path.getComponent("//lbl3")).setValue(org.zkoss.util.resource.Labels.getLabel("app.title.setByJavaCode"));

Other sources of examples

edit
  • The Developer's guide of course ;-) and other resources on the documentation-page, including the zk-forums.
  • In the Small Talks on zkoss you can find many examples regarding zul, hibernate, spring framework and many others with source code included.
  • An article on developer.com shows an example of a student enrollment. Source code is available. It includes a tree, a listbox, tabs and shows f.i. the drag and drop functionality.
  • An article on IBM shows the usage of the included jgraph with zk.
  • Another article on IBM shows how to upload images to a database.