Getting Started"

From Documentation
Line 230: Line 230:
 
</source>
 
</source>
  
where we assume <tt>foo.User</tt> has three methods: <tt>getName()</tt>, <tt>getTitle()</tt> and <tt>getAge()</tt>.
+
where we assume <tt>foo.User</tt> has three methods: <tt>getName()</tt>, <tt>getTitle()</tt> and <tt>getAge()</tt>. <tt>forEach</tt> is used to instantiate components by iterating through a collection of objects.
  
 
[[File:DgGettingStartedUsers.png]]
 
[[File:DgGettingStartedUsers.png]]

Revision as of 06:29, 5 September 2010

Getting Started


Stop.png This documentation is for an older version of ZK. For the latest one, please click here.


This chapter describes how to write your first ZUML (ZK User interface Markup Language) page, and demonstrates some ZK's features in really simple examples.

Hello World!

After ZK is installed into your favorite Web server[1], writing applications is straightforward. Just create a ZUML file, say hello.zul[2], as follows under one of the Web application's directories just like as you do for a HTML file.

 <window title="My First ZK Application" border="normal">
 	Hello World!
 </window>


Then, browse to the right URL, say http://localhost/myapp/hello.zul, and you got it.

DgGettingStartedHello.zul.png

In a ZUML page, a XML element describes what component to create. In this example, it is a window . The XML attributes are used to assign values to properties of the window component. In this example, it sets the window's title to "My First ZK Application" and border to normal.

The text enclosed in the XML elements is also interpreted as a special component called label. Thus, the above example is equivalent to the following.

 <window title="My First ZK Application" border="normal">
	<label value="Hello World!"/>
</window>

  1. Refer to the Quick Start Guide.
  2. The other way to try examples is to use ZK Sandbox to run them.

Say Hello in Ajax way

Let us put some interactivity into it.

 <button label="Say Hello" onClick='Messagebox.show("Hello World!")'/>

Then, when you click the button, you see as follows.

DgGettingStartedHello2.png

The onClick attribute is a special attribute used to add an event listener to the component, such that it is invoked when an end user clicks it. The attribute value could be any legal Java code. Notice that it is not JavaScript, and we have to use the double quotes (") to represent a string. Furthermore, to specify a double quote in a XML attribute, we could use single quotes (') to enclose it[1].

Here we invoke Messagebox.show(String) to show a message box as depicted above.

The Java code is interpreted by BeanShell at run time. In additions to event handling, we could embed the code in a ZUML page by specifying it in a special element called zscript. For example, we could define a function to simply the code as follows.

 <window title="My First ZK Application" border="normal">
 	<button label="Say Hello" onClick='alert("Hello World!")'/>
 	<zscript>
 		void alert(String message){ //declare a function
 			Messagebox.show(message);
 		}
 	</zscript>
 </window>

In fact, alert is a built-in function that you can use it directly in the embedded Java code.


  1. If you are not familiar with XML, you might take a look at the XML section.

It is Java and runs at the server

The embedded Java code runs at the server so it could access any resource available at the server. For example,

<window title="Property Retrieval" border="normal">
    Enter a property name: <textbox/>
    <button label="Retrieve" onClick="alert(System.getProperty(self.getPreviousSibling().getValue()))"/>
</window>

where self is a built-in variable that references to the component receiving the event.

If we entered java.version and clicks the button, the result is as follows.

DgGettingStartedProperty.png

Access Component by ID

The access of a component is easier if you assigned an identifier to it. For example, the above code can be simplified if we named the textbox as input as shown below.

<window title="Property Retrieval" border="normal">
    Enter a property name: <textbox id="input"/>
    <button label="Retrieve" onClick="alert(System.getProperty(input.getValue()))"/>
</window>

A component is a POJO

A component is a POJO. You could instantiate and manipulate directly. For example, we could generate the result by instantiating a component to represent it, and then append it to another component (an instance of vlayout).

<window title="Property Retrieval" border="normal">
    Enter a property name: <textbox id="input"/>
    <button label="Retrieve" onClick="result.appendChild(new Label(System.getProperty(input.getValue())))"/>
    <vlayout id="result"/>
</window>

Similarly you could change the state of a component directly. All modifications will be synchronized back to the client automatically.

<window title="Property Retrieval" border="normal">
    Enter a property name: <textbox id="input"/>
    <button label="Retrieve" onClick="result.setValue(System.getProperty(input.getValue()))"/>
    <separator/>
    <label id="result"/>
</window>

MVC: Separating code from user interface

Embedding Java code in a ZUML page is straightforward and easy to read. However, in a production environment, it is usually better to separate the code from the user interfaces. In additions, the compiled Java code runs much faster than the embedded code which is interpreted at the run time.

To separate code from UI, we could implement a Java class (aka., the controller) that implements Composer, and then handle UI in Composer.doAfterCompose(Component). For example, we can redo the previous example by registering an event listener in Composer.doAfterCompose(Component), and then retrieve the result and instantiate a label to represent it in the event listener as follows.

package foo;
import org.zkoss.zk.ui.Component;
import org.zkoss.zk.ui.util.Composer;
import org.zkoss.zk.event.EventListener;
import org.zkoss.zul.Label;

public class PropertyRetriever implements Composer {
    public void doAfterCompose(Component target) { //handle UI here
        target.addEventListener("onClick", new EventListener() { //add a event listener in Java
            public void onEvent(Event event) {
                String prop = System.getProperty(target.getFellow("input").getValue());
                target.getFellow("result").appendChild(new Label(prop));
            }
        });
    }
}

As shown, an event listener could be registered by use of Component.addEventListener(String, EventListener). An event listener must implement EventListener, and then handle the event in EventListener.onEvent(org.zkoss.zk.ui.event.Event.

Also notice that a component assigned with an identifier could be retrieved by use of Component.getFellow(String).

Then, we could associate the controller (foo.PropertyRetriever) with a component by use of the apply attribute as shown below.

<window title="Property Retrieval" border="normal">
    Enter a property name: <textbox id="input"/>
    <button label="Retrieve" apply="foo.PropertyRetriever"/>
    <vlayout id="result"/>
</window>

MVC: Autowiring

Implementing and registering event listeners is a bit tedious. Thus, ZK provides a feature called autowiring. By extending from GenericForwardComposer, ZK will looks for the members if their names match the identifiers of components. For example, we could rewrite foo.PropertyRetriever by utilizing the autowriing as follows.

package foo;
import org.zkoss.zk.ui.Component;
import org.zkoss.zk.ui.util.GenericForwardComposer;
import org.zkoss.zul.*;

public class PropertyRetriever extends GenericForwardComposer {
    Textbox input;
    Vlayout result;

    public retrieve$onClick(Event event) {
        //handle onClick of the retrieve button
        String prop = System.getProperty(input.getValue());
        result.appendChild(new Label(prop));
    }
}

and the ZUL page is as follows.

<window title="Property Retrieval" border="normal" apply="foo.PropertyRetriever">
    Enter a property name: <textbox id="input"/>
    <button label="Retrieve" id="retrieve"/>
    <vlayout id="result"/>
</window>

As shown above, input and result are automatically assigned such that we could access the real components directly. Also retrieve$onClick indicates an event listener will be registered to the component called retrieve to handle the onClick event.

Notice that MVC is recommended for a production application. On the other hand, for sake of easy-to-read, most of examples in our documents embed code directly in ZUML pages.

Express data with variable resolver and EL expressions

In a ZUML page, we could locate data with a variable resolver (VariableResolver), and then express it with EL expressions.

For example, assumes we have a class called foo.User, and we can retrieve a list of users by its static method called getAll(). Then, we can implement a variable resolver as follows.

package foo;
public UserResolver implements org.zkoss.xel.VariableResolver {
    public Object resolveVariable(String name) {
        return "users".equals(name) ? Users.getAll(): null;
}

And, we can list all users as follows.

<?variable-resolver class="foo.VariableResolver"?>
<grid>
    <columns>
        <column label="Name" sort="auto"/>
        <column label="Title" sort="auto"/>
        <column label="Age" sort="auto"/>
    </columns>
    <rows>
        <row forEach="${users}">
            <label value="${each.name}"/>
            <label value="${each.title}"/>
            <label value="${each.age}"/>
        </row>
    </rows>
</grid>

where we assume foo.User has three methods: getName(), getTitle() and getAge(). forEach is used to instantiate components by iterating through a collection of objects.

DgGettingStartedUsers.png

Quiz

  1. What event is triggered when a button is clicked?
  2. What element should be used if you want to embed Java code in ZUML?
  3. Why to assign an identifier to a component?
  4. What does ${expr} mean?
  5. Is it better to embed Java code in ZUML or to use MVC in a production application?



Last Update : 2010/09/05

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