ZK 5.0.7 Component Development Essentials

29
PDF generated using the open source mwlib toolkit. See http://code.pediapress.com/ for more information. PDF generated at: Wed, 11 May 2011 09:41:04 CST ZK Component Development Essentials For ZK 5.0.7

Transcript of ZK 5.0.7 Component Development Essentials

Page 1: ZK 5.0.7 Component Development Essentials

PDF generated using the open source mwlib toolkit. See http://code.pediapress.com/ for more information.PDF generated at: Wed, 11 May 2011 09:41:04 CST

ZK Component DevelopmentEssentialsFor ZK 5.0.7

Page 2: ZK 5.0.7 Component Development Essentials

ContentsArticles

ZK Component Development Essentials 1 ZK Component Overview 1 What is a ZK component 1 How does a ZK Component work 2 Development Tools 3 Creating a simple ZK Component 3 ZK's JavaScript Extension 3 Implementing the Component 4 Implementing a Component Property 5 Render All Properties to the Client 6 Putting it all Together 7 Implementing the Widget 8 Implementing a Widget Property 9 Putting it all Together 10 Rendering Widgets 11 Implementing Molds 11 The Redraw Method 12 Creating the Configuration Files 12 The language-addon 12 The Widget Package Descriptor 13 Handling Events 15 How we Implement the Event 15 Overriding bind and unbind 16 Registering Appropriate Listeners 17 Client-Server Communication 18 Server-side Listeners 20 Declaring an Important Event 21 Packing as a Jar 21 Conclusion 25

ReferencesArticle Sources and Contributors 26Image Sources, Licenses and Contributors 27

Page 3: ZK 5.0.7 Component Development Essentials

ZK Component Development Essentials 1

ZK Component Development EssentialsDocumentation:Books/ZK_Component_Development_Essentials

If you have any feedback regarding this book, please leave it here.<comment>http:/ / books. zkoss. org/ wiki/ ZK_Component_Development_Essentials2</comment>

ZK Component Overview This section provides an overview to ZK Component development.

What is a ZK component Each UI object in ZK consists of a component and a widget.

ComponentA component is a Java object running at the server which represents a UI object which can be manipulated by a Javaapplication. A component has all the behavior of a UI object except it has no visual part.

WidgetA widget is a JavaScript object running at the client. This object represents the UI object which interacts with theuser. Therefore, a widget usually has a visual appearance, and handles events happening at the client.Having established that there are two parts to a ZK Component one needs to explore how these parts interact to forma fully interactive user experience.

Page 4: ZK 5.0.7 Component Development Essentials

How does a ZK Component work 2

How does a ZK Component work A component and a widget work hand in hand to deliver a rich UI experience to a user. The widget traps the useractivity and sends an appropriate request to the component. The component then interacts with the developer’sApplication and responds appropriates telling the widget to update. This interaction is demonstrated in the followingdiagram.

For example, when an application invokes the setLabel method to change the label of a button component, thesetLabel method of corresponding button widget (aka., peer widget) will be invoked at the client to change the visualappearance (as shown below).

When the user clicks the button widget, the onClick event will be sent back to the server and notify the application(as demonstrated below).

In additions to manipulate a component at the server, it is also possible to control a widget at the client. For example,an application may hide or change the order of grid columns at the client, while the application running at the serverhandles the reloading of the grid’s content. This technique is called Server+client fusion. It can be used to improveresponsiveness and reduce network traffic.

Page 5: ZK 5.0.7 Component Development Essentials

Development Tools 3

Development Tools Here is a list of development tools. Though optional, they are helpful in many situations.

Tool Description

ZK CDT [1] A component development tool providing wizards to simplify the creation of components.

Firebug [2] A JavaScript debugger. It is an addon for Firefox. It is not built-in, so you have to download and install itseparately.

Internet Explorer 9 DeveloperTools

It is built-in and you could start it by pressing F12.

References[1] http:/ / code. google. com/ a/ eclipselabs. org/ p/ zk-cdt/[2] http:/ / getfirebug. com/

Creating a simple ZK Component This section provides instructions on how to create a ZK component.

ZK's JavaScript Extension To make it easier for JavaScript objects to represent widgets ZK has introduced a class concept to JavaScript. Here isa brief introduction on defining a class in JavaScript.To define a new class in JavaScript, we use _global_.Map, _global_.Map) zk.$extends(zk.Class, _global_.Map,_global_.Map) [1].

zk.$package('com.foo');

com.foo.Location = zk.$extends(zk.Object, {

x: 0,

y: 0,

distance: function (loc) {

return Math.sqrt(Math.pow(this.x - loc.x, 2) + Math.pow(this.y -

loc.y, 2));

}

},{

find: function (name) {

if (name == 'ZK')

return new com.foo.Location(10, 10);

throw 'unknown: "+name;

}

})

The first argument of _global_.Map, _global_.Map) zk.$extends(zk.Class, _global_.Map, _global_.Map) [1] is the base class to extend from. In this case, we extend from Object [2], which is the root of the class hierarchy. The

Page 6: ZK 5.0.7 Component Development Essentials

ZK's JavaScript Extension 4

second argument consists of the (non-static) members of the class. In this case, we define two data members (x andy) and one method (distance).The third argument is optional and if omitted means that the extended class will contain no static members. In theexample we define a static method (<mp>find</mp>). For now this is all that is required for us to create our firstcomponent so let’s move onto talk about the component implementation.

References[1] http:/ / www. zkoss. org/ javadoc/ latest/ jsdoc/ _global_/ zk. html#$extends(zk. Class,[2] http:/ / www. zkoss. org/ javadoc/ latest/ jsdoc/ zk/ Object. html#

Implementing the Component As previously mentioned a ZK Component consists of a server-side component usually written in Java and a clientbased widget written in JavaScript. Firstly let’s discuss the creation of the server-side component.The component’s Java class must extend AbstractComponent [1] or one of its derivative classes. There are severalderived classes all providing different levels of functionality. The derived classes are shown below.

For tutorial purpose, we use HtmlBasedComponent [2], which is the base class for HTML-based component.To implement a component class, we need to decide on• The class name. Let’s name it <mp>com.foo.SimpleLabel</mp>• The properties to support. In this case, we'd like to implement a property called value, which is the visual content

at the client.Let’s investigate the component properties.

Page 7: ZK 5.0.7 Component Development Essentials

Implementing the Component 5

References[1] http:/ / www. zkoss. org/ javadoc/ latest/ zk/ org/ zkoss/ zk/ ui/ AbstractComponent. html#[2] http:/ / www. zkoss. org/ javadoc/ latest/ zk/ org/ zkoss/ zk/ ui/ HtmlBasedComponent. html#

Implementing a Component Property A property usually has a getter and a setter. The getter is straightforward:

private String _value = ""; //a data member

public String getValue() {

return _value;

}

The setter is similar except we have to notify the client. This is achieved by using the java.lang.Object)AbstractComponent.smartUpdate(java.lang.String, java.lang.Object) [1] function.

public void setValue(String value) {

if (!_value.equals(value)) {

_value = value;

smartUpdate("value", _value);

}

}

The java.lang.Object) AbstractComponent.smartUpdate(java.lang.String, java.lang.Object) [1] function causes ZKClient Engine to call the <mp>setValue</mp> method of the peer widget (the first argument is the property name).Then, the widget can manipulate the DOM tree from there.

References[1] http:/ / www. zkoss. org/ javadoc/ latest/ zk/ org/ zkoss/ zk/ ui/ AbstractComponent. html#smartUpdate(java. lang. String,

Page 8: ZK 5.0.7 Component Development Essentials

Render All Properties to the Client 6

Render All Properties to the Client When a component is attached to a page at the first time, the renderProperties(org.zkoss.zk.ui.sys.ContentRenderer)[1] method is called to render all properties that will be sent to the client for creating a peer widget. All requiredproperties have to be rendered such that the client can create a peer widget with the same set of properties.Implementing renderProperties(org.zkoss.zk.ui.sys.ContentRenderer) [1] is straightforward. As shown below, all youneed to do is to invoke <mp>super.renderProperties</mp> to render all inherited properties (such as width andheight), and then the render method to render the property defined in this class.

protected void renderProperties(org.zkoss.zk.ui.sys.ContentRenderer

renderer)

throws java.io.IOException {

super.renderProperties(renderer);

render(renderer, "value", _value);

}

Why renderProperties and smartUpdate?

A common question is why renderProperties(org.zkoss.zk.ui.sys.ContentRenderer) [1] (and redraw(java.io.Writer)[2]) is required to render value again, when we notify the client with boolean) smartUpdate(java.lang.String, boolean)[1] in setValue?The simple answer is renderProperties is used to send all properties at once, when a component is going to beattached to the page at the client. On the other hand, boolean) smartUpdate(java.lang.String, boolean) [1] is used tosend a property that was modified after the peer widget is attached at the client. ZK will minimize the traffic byremoving unnecessary boolean) smartUpdate(java.lang.String, boolean) [1] (if renderProperties is called).Once a widget is attached to the page at the client, renderProperties won’t be called. If you want to regenerate allproperties and rerender it at the client, you can invoke the invalidate method. Note that if you update a propertymultiple times in the same execution (with boolean) smartUpdate(java.lang.String, boolean) [1]), only the last valuewill be sent to the client. If you prefer to send them all (rather than overwriting), then you can set the 3rd argumentappend to true (java.lang.Object, boolean) smartUpdate(java.lang.String, java.lang.Object, boolean) [1]). For exampleyou may use this when adding a listener for a certain event and you do not want to overwrite the present listener thisis achieved by passing true as the third argument of boolean) smartUpdate(java.lang.String, boolean) [1]. The tablebelow outlines the differences.

smartUpdate smartUpdate (append, 3rd argument true)

Sent to client if invalidated or new created No No

Sent to client if the component isremoved

No No

Sent to client if name is the same Only the last value is sent Yes

Page 9: ZK 5.0.7 Component Development Essentials

Render All Properties to the Client 7

References[1] http:/ / www. zkoss. org/ javadoc/ latest/ zk/ org/ zkoss/ zk/ ui/ AbstractComponent. html#renderProperties(org. zkoss. zk. ui. sys.

ContentRenderer)[2] http:/ / www. zkoss. org/ javadoc/ latest/ zk/ org/ zkoss/ zk/ ui/ AbstractComponent. html#redraw(java. io. Writer)

Putting it all Together Finally we put all the component information together to produce the result below.

package com.foo;

public class SimpleLabel extends org.zkoss.zk.ui.HtmlBasedComponent {

private String _value = ""; // a data member

public String getValue() {

return _value;

}

public void setValue(String value) {

if (!_value.equals(value)) {

_value = value;

smartUpdate("value", _value);

}

}

protected void

renderProperties(org.zkoss.zk.ui.sys.ContentRenderer renderer)

throws java.io.IOException {

super.renderProperties(renderer);

render(renderer, "value", _value);

}

}

Having implemented the Component we now need to implement the Widget.

Page 10: ZK 5.0.7 Component Development Essentials

Implementing the Widget 8

Implementing the Widget The widget class must extend from Widget [1] or one of its derived classes. There are several skeletalimplementations available. The skeletal implementations are shown in the image below.

For the purposes of this tutorial, we will use Widget [1]. Before we proceed, we need to decide the name of thewidget class. Let’s assume <mp>com.foo.SimpleLabel</mp>.

References[1] http:/ / www. zkoss. org/ javadoc/ latest/ jsdoc/ zk/ Widget. html#

Page 11: ZK 5.0.7 Component Development Essentials

Implementing a Widget Property 9

Implementing a Widget Property A property usually has a getter and a setter. The getter is straightforward:

_value: '', //default value

getValue: function () {

return this._value;

}

The setter is defined in a similar manner except we have to modify the DOM tree if it has been attached. A widgetinherits a property called node which is assigned a reference to a DOM element if the widget has been attached to theDOM tree. If a widget is attached to DOM, <mp>this.desktop</mp> will be a reference to the desktop (Desktop [1])it belongs. Otherwise, it is null.How we update depends on the DOM content. In this example, we use HTML's span to enclose the value, so we onlyneed to change innerHTML.

setValue: function(value) {

if (this._value != value) {

this._value = value;

if (this.desktop) this.$n().innerHTML = zUtl.encodeXML(value);

}

}

References[1] http:/ / www. zkoss. org/ javadoc/ latest/ zk/ zk/ Desktop. html#

Page 12: ZK 5.0.7 Component Development Essentials

Putting it all Together 10

Putting it all Together The widget implementation must be placed in an independent JavaScript file. The file must be placed under thedirectory, /web/js/package-path, in the Java class path. Since the widget name is SimpleLabel and the packagename is com.foo, the file path is /web/js/com/foo/SimpleLabel.js.

com.foo.SimpleLabel = zk.$extends(zk.Widget, {

_value : '', // default value

getValue : function() {

return this._value;

},

setValue : function(value) {

if (this._value != value) {

this._value = value;

if (this.desktop)

this.$n().innerHTML = zUtl.encodeXML(value);

}

}

});

Having set-up the ability to handle states we now need to create the component view. This can be accomplishedusing two methods.

Page 13: ZK 5.0.7 Component Development Essentials

Rendering Widgets 11

Rendering Widgets Rendering of widgets can be achieved using two methods. The first is named mold which enables a widget to havemultiple display types which a developer or user can select at will. The second is a redraw method which onlysupports one type of view. Firstly let us discuss how to implement a mold.

Implementing Molds A widget can have several molds. Each mold needs to be placed in an independent JavaScript file. Under asubdirectory named mold. The full path of the directory in this example will be/web/js/com/foo/mold/simple-label.js.Let us assume we want to generate the following DOM content:<mp>value</mp>Then, the content of simple-label.js will be as follows.

function (out) {

out.push('<span', this.domAttrs_(), '>', this.getValue(), '</span>');

}

As shown above, the mold is actually a JavaScript method. More precisely, it is a method member of the widgetclass (the name is assigned by ZK Client Engine automatically), so you can access the widget object by use of this.The mold method takes an argument named out, which behaves like a writer in Java. The out object at leastimplements the push and unshift method to write the content to the end or to the beginning. It is by default an array,but the client application might use different kinds of objects.<mp>domAttrs_</mp> is a (protected) method inherited from Widget [1]. It returns all HTML attributes required,such as style, id and so on. You can override it if you want.If we do not require multiple styles per component we can just implement the redraw method directly.

Page 14: ZK 5.0.7 Component Development Essentials

The Redraw Method 12

The Redraw Method When a widget is attached to the DOM tree, Widget.redraw(_global_.Array) [1] is called to generate the HTMLcontent. For example, assume you want to use <mp>HTML SPAN</mp> tag to house the content, we can do asfollows.

redraw: function (out) {

out.push('<span', this.domAttrs_(), '>', this.getValue(), '</span>');

}

The default implementation of Widget.redraw(_global_.Array) [1] delegates to a mold method depending on themold. In this instance we override the function to provide one implementation of redraw which doesn’t use molds.

References[1] http:/ / www. zkoss. org/ javadoc/ latest/ jsdoc/ zk/ Widget. html#redraw(_global_. Array)

Creating the Configuration Files In order for our component to be used in ZK applications we need to provide two component files namedlanguage-addon and zk.wpd.

The language-addon The language-addon contains a description of the relation between the component and widget referred to as thecomponent definition. The path of the file must be /metainfo/zk/lang-addon.xml and be located in the Java classpath.

<language-addon>

<addon-name>simplelabel</addon-name>

<language-name>xul/html</language-name>

<component>

<component-name>simplelabel</component-name>

<component-class>com.foo.SimpleLabel</component-class>

<widget-class>com.foo.SimpleLabel</widget-class>

<mold>

<mold-name>default</mold-name>

<mold-uri>mold/simple-label.js</mold-uri>

<css-uri>css/simple-label.css.dsp</css-uri>

</mold>

</component>

</language-addon>

The table below describes the elements used within the above XML and their descriptions.

Page 15: ZK 5.0.7 Component Development Essentials

The language-addon 13

Name Description

addon-name A unique name for this addon

language-name The language name that this addon belongs to (for instance, xul/html orzhtml)

component-name A unique name of the component in the language of this addon

component-class The name of the component class (Java class)

widget-class The name of the widget class (JavaScript class)

mold A mold definition (optional)

mold-name The name of the mold. The default mold is named default.

mold-uri The URI of the mold

css-uri The URI of the CSS file for the mold

A component may have multiple molds which may or may not have different widget classes. To handle this you mayspecify the <widget-class> inside <mold>. You can specify more than one mold.After creating the component descriptor language-addon we need to create the widget package descriptor.For more information, please refer to ZK Client-side Reference: Language Definition.

The Widget Package Descriptor The Widget Package Descriptor (WPD) is a file describing the information of a package, such as its widget classesand external JavaScript files. WPD must be named zk.wpd and placed in the same directory as the widget classes.For example we would place it under web/js/com/foo.Below an example zk.wpd of our SimpleLabel.

<package name="com.foo" language="xul/html">

<widget name="SimpleLabel"/>

</package>

The table below describes the elements used within the above XML and their descriptions.

Name Description

package The root element denotes the package name and the language it belongs to

widget The widget class name (without the package name). If the package contains multiple widgets list them one by one

Having created the configuration the basic implementation of our component is complete. However it doesn』t haveany interactive events. Therefore the next logical step is to start adding events to the component.

Page 16: ZK 5.0.7 Component Development Essentials

The Widget Package Descriptor 14

Package DependenceIt is common for JavaScript packages to depend on another package. For example, zul.grid depends onzul.mesh and zul.menu. This can easily be specified by placing them within the depends attribute asfollows.

<package name="zul.grid" language="xul/html" depends="zul.mesh,zul.menu">

<widget name="Column"/>

<widget name="Columns"/>

<widget name="Grid"/>

<widget name="Row"/>

<widget name="Rows"/>

<widget name="Foot"/>

<widget name="Footer"/>

</package>

Including additonal JavaScript filesIf a JavaScript package has to include other JavaScript files, this can be done easily by specifying the file with thescript element. For example, the following is the content of zul.db's WPD:

<package name="zul.db" language="xul/html" depends="zk.fmt,zul.inp">

<script src="datefmt.js"/>

<widget name="Calendar"/>

<widget name="Datebox"/>

</package>

For more information, please refer to ZK Client-side Reference: Widget Package Descriptor.

Page 17: ZK 5.0.7 Component Development Essentials

Handling Events 15

Handling Events The next logical step is to add an event to our ZK component. To this we are going add some more functionality tothe SimpleLabel. A new div will be added which when clicked should clear the displayed text and fire a customevent named <mp>onClear</mp>.This means that firstly we need to change the mold of the label to include a div which can be used as a target. Thecode below satisfies this requirement:

function (out) {

out.push('<span', this.domAttrs_(), '><div id="value" style="float:left;">', this.getValue(), '</div><div id="target" style="float:left;cursor: pointer; cursor: hand;height:20px;width:20px;background-color:red;"></div></span>');

}

As you can see we have now split the contents of label into two by introducing two div tags, one will be used todisplay the value and the other will be a click target.

How we Implement the Event To implement the required event we need to follow these steps:1. Override zk.Skipper, _global_.Array) bind_(zk.Desktop, zk.Skipper, _global_.Array) [1] and _global_.Array)

unbind_(zk.Skipper, _global_.Array) [2]

2. Register the appropriate listener

References[1] http:/ / www. zkoss. org/ javadoc/ latest/ jsdoc/ zk/ Widget. html#bind_(zk. Desktop,[2] http:/ / www. zkoss. org/ javadoc/ latest/ jsdoc/ zk/ Widget. html#unbind_(zk. Skipper,

Page 18: ZK 5.0.7 Component Development Essentials

Overriding bind and unbind 16

Overriding bind and unbind The following diagrams outline when the zk.Skipper, _global_.Array) bind_(zk.Desktop, zk.Skipper,_global_.Array) [1] and _global_.Array) unbind_(zk.Skipper, _global_.Array) [2] methods are called. Firstly let’s takea look at how binding works.

The _global_.Array) unbind_(zk.Skipper, _global_.Array) [2] function is very similar. Upon detaching of the widgetfrom the DOM the _global_.Array) unbind_(zk.Skipper, _global_.Array) [2] method is called enabling us to performtasks such as adding and removing listeners to avoid memory leaks. The diagram below demonstrates this.

Now that we have had a brief introduction of zk.Skipper, _global_.Array) bind_(zk.Desktop, zk.Skipper,_global_.Array) [1] and _global_.Array) unbind_(zk.Skipper, _global_.Array) [2] let’s see the methods put into actionwhen we bind appropriate listeners for events.

Page 19: ZK 5.0.7 Component Development Essentials

Registering Appropriate Listeners 17

Registering Appropriate Listeners Registering listeners is a fundamental of many programming languages and event driven applications. Being anevent driven framework ZK is no different. To accomplish our goal of a clear button we need to do two things:1. Capture clicks on our "target"2. Fire a custom <mp>onClear</mp> event when the target is clicked

Capturing Clicks on our TargetFirstly, let’s concentrate on capturing clicks on our target div. To do so we need to register appropriate listeners inthe bind_ method and remove the listeners in the unbind_ method to avoid any memory leak. Here is the code to doso.

bind_ : function(evt) {

this.$supers('bind_', arguments);

this.domListen_(this.$n().lastChild, "onClick",

'_doClear');

},

unbind_ : function(evt) {

this.domUnlisten_(this.$n().lastChild, "onClick",

'_doClear');

this.$supers('unbind_', arguments);

},

The key to this is the domListen method which takes the target as the first parameter, in this case we pass it the<mp>lastChild</mp> which is our target, the name of the event you want to listen for as the second parameter andfinally the name of the callback.Please note that you also are required to call <mp>$supers</mp> so that parent classes can register and remove theirevents successfully. Now we need to move on to firing our custom <mp>"onClear"</mp> event, let’s take a look athow to do this.

Firing a Custom Event (onClear)The key lies in the registering the callback of the event. In our case we registered a callback named<mp>"_doClear"</mp>. In this <mp>_doClear</mp> method we need to clear/restore the text depending on thewidget state and fire the onClear method. The code is as follows:

_doClear: function(evt) {

this._cleared = !(this._cleared);

if(this._cleared) {

this.$n().firstChild.innerHTML = this._value;

} else {

this.$n().firstChild.innerHTML = "";

}

this.fire("onClear", {cleared: this._cleared});

Page 20: ZK 5.0.7 Component Development Essentials

Registering Appropriate Listeners 18

}

We have a data member named _cleared which contains the state of the application. Depending on the state themethod either shows or clears the displayed value. The method <mp>onClear</mp> is then fired and the clearedstate is sent along with the instruction to fire the event.The client side widget will now communicate with the component at the server side. This is handled by ZK. Thefollowing section explores how this communication works.

Client-Server Communication The following diagram outlines how communication works between a ZK Widget and Component.

zk.Object, _global_.Map, int) Widget.fire(_global_.String, zk.Object, _global_.Map, int) [1] fires a client event (aninstance of Event [2]), and the client event is converted to an AU request if all the following conditions are satisfied.• The widget is a peer of a component, that is, it was created automatically to represent a component. Notice that

the Server states whether a widget is a peer of a component.• The event propagation is not stopped (i.e., zk.Object, _global_.Map, int) Widget.fire(_global_.String, zk.Object,

_global_.Map, int) [1] not set.• The event is listened by a server-side Listener [3], or it is an important event.The above image demonstrates that the onClear event is sent to the server and processed. The code to do is located inthe component’s Java file SimpleLabel.java and is as follows.

public void service(org.zkoss.zk.au.AuRequest request, boolean

everError) {

final String cmd = request.getCommand();

if (cmd.equals(ClearEvent.NAME)) {

ClearEvent evt = ClearEvent.getClearEvent(request);

_cleared = evt.getCleared();

Events.postEvent(evt);

Page 21: ZK 5.0.7 Component Development Essentials

Client-Server Communication 19

} else

super.service(request, everError);

}

Here the ClearEvent is in fact a completely customized event created for the purposes of this component. The eventis created using its static method <mp>getClearEvent</mp>, shown below.

public static final ClearEvent getClearEvent(AuRequest request) {

final Component comp = request.getComponent();

final Map data=request.getData();

boolean cleared = AuRequests.getBoolean(data, "cleared");

return new ClearEvent(request.getCommand(), comp, cleared);

}

The retrieval of the event is easy as the ClearEvent extends Event and its constructor has the following signaturepublic ClearEvent(String name, Component target, boolean cleared). The only custom information is theBoolean cleared which is the state we sent back when the event was fired. As demonstrated in the above code this iseasily acquired using the java.lang.String) AuRequests.getBoolean(java.util.Map, java.lang.String) [4].We have now followed the process of how data is transferred between the client and server. Of course when buildingcomponent we also need to specify server side listeners to invoke Java code on calling of specific events, let’sinvestigate this.

References[1] http:/ / www. zkoss. org/ javadoc/ latest/ jsdoc/ zk/ Widget. html#fire(_global_. String,[2] http:/ / www. zkoss. org/ javadoc/ latest/ jsdoc/ zk/ Event. html#[3] http:/ / www. zkoss. org/ javadoc/ latest/ zk/ org/ zkoss/ zk/ ui/ Listener. html#[4] http:/ / www. zkoss. org/ javadoc/ latest/ zk/ org/ zkoss/ zk/ au/ AuRequests. html#getBoolean(java. util. Map,

Page 22: ZK 5.0.7 Component Development Essentials

Server-side Listeners 20

Server-side Listeners Then we move on and fire the <mp>"onClear"</mp> event. To fully understand what happens next we now need toinvestigate server side listeners which handle these events. A client event will not be sent to the server if it has notbeen registered. To give the developer the ability to register an event listener at the serverside we need to declare theevents. We do this using the function addClientEvent.The following example demonstrates declaring a clear event at the server.

static {

addClientEvent(SimpleLabel.class, ClearEvent.NAME, 0);

}

We have noted that if an event is not registered at the server side then it will not be sent from the client. However, inour example there is a problem if the event is not sent back. Let’s cast our mind back to the service method weimplemented.

public void service(org.zkoss.zk.au.AuRequest request, boolean

everError) {

final String cmd = request.getCommand();

if (cmd.equals(ClearEvent.NAME)) {

ClearEvent evt = ClearEvent.getClearEvent(request);

_cleared = evt.getCleared();

Events.postEvent(evt);

} else

super.service(request, everError);

}

Notice that on the receipt of the <mp>ClearEvent</mp> we update the <mp>_cleared</mp> property at the serverside. Imagine if this event is not sent then we have a problem as the client and server side will be out of sync. To getaround this we can register the event as important.

Page 23: ZK 5.0.7 Component Development Essentials

Declaring an Important Event 21

Declaring an Important Event The third argument of <mp>addClientEvent</mp> is used to declare an event as import. The argument is acombination of integer flags that indicate how to handle the event. The CE_IMPORTANT flag is used to indicatethat this event is very important and should be sent to the server even if there is no server side listener registered forthe event. For other flags, please refer to the Java API.For example, we require the <mp>onClear</mp> event to be sent to the server at all times so we are required todeclare the following:

static {

addClientEvent(SimpleLabel.class, ClearEvent.NAME,

CE_IMPORTANT);

}

Now the ClearEvent is guaranteed to be sent to the server which solves our syncing problem. Now we have a simplelabel with some additional features which works as advertised. This label has served as a good introduction tocomponent development with ZK.

Packing as a Jar

Jar FilesPacking a component as a Jar file will make it easy to deployment, this article is telling you steps and requirementsof it.

• Requirements of a component Jar

Configurations

Component classes

Widget Resources

Static Resources

what do they look like , example from zul.jar

Configurations

Page 24: ZK 5.0.7 Component Development Essentials

Packing as a Jar 22

File Structure

• /META-INF/

• MANIFEST.MF• /metainfo/

• mesg/

• msg<jar name>.properties(optional)• msg<jar name>_<locale>.properties (optional ...)

• xml/

• <component-name>.xsd (optional)• zk/

• lang.xml (optional)• lang-addon.xml (optional)

The example from zul.jar

File descriptions

• /META-INF/

• MANIFEST.MF

• The file for jar defino• /metainfo/

• mesg/

• msg<jar name>.properties

• These files are i18n resource files,you can define with the locale you want , the default file ismsg<jar name>.properties.ZK Internationalization

• xml/

• <jar-name>.xsd

• The xml schema for component tags in zul• tld

• config.xml

• For taglibs definition. (ex. zweb.jar use this for dsp.) • zk/

• lang-addon.xml

• The language add-on define components , and it defined the component classes, javascriptwidget/mold/css.it should contains At least one lang.xml or lang-addon.xml usually you will need alang-addon.xml .

• lang.xml

• The language definition file with namespace (ex. http:/ / www. w3. org/ 1999/ xhtml for zhtml)

Component classes

Page 25: ZK 5.0.7 Component Development Essentials

Packing as a Jar 23

File Structure

• /package-folder

• classes

File descriptions

• The java classes of component. just like normal jarfile.

The example from zul.jar

Widget Resources

File Structure

• /web/

• js/

• component-package/

• mold/

• <widget-mold-js-file>• css/

• <widget-css-dsp-file> (optional)• <widget-css-file> (optional)

• <widget-class-js-file>• /zk.wpd

Example for box from zul.jar

File descriptions

• /web/

• js/

• <component-package>/

• mold/

• <widget-mold-js-file> (ex. simple-label.js )

• Widget mold file , you can write widget's html with javascript functionhere.

• css/

• <widget-css-dsp-file> (ex. simple-label.css.dsp )

• The css dsp files ,in the dsp you can use some variable with zkenviroment to write it.

• <widget-css-file> (ex. simple-label.css )

• the pure css files.• <widget-class-file> (ex. Simple-label.js)

• The widget class you write .• zk.wpd

• Define your component's package and widgets here, and the dependencywith other package.

Page 26: ZK 5.0.7 Component Development Essentials

Packing as a Jar 24

Static Resources

File Structure

• /web/

• <component-package> / (optional)

• css /(optional)

• <css files>(optional)• zk.wcs(optional)

• img /(optional)

• <img files>(optional)

Example fromzul.jar

File descriptions

• /web/

• <component-package>/

• css/

• <css files>

• For some static css file you might need. • zk.wcs

• Let you can config the CSS file for particular language • img/

• <img files>

• This is a folder for some image files , and you can access them in xxx.css.dsp files through${c:encodeURL('~./img/<component-package>/xxx.png')}

Page 27: ZK 5.0.7 Component Development Essentials

Conclusion 25

Conclusion At this point we have enough knowledge to go ahead and produce components for ZK. The next port of call foradvancing our skills is ZK’s source code itself which exposes hundreds of components.

Page 28: ZK 5.0.7 Component Development Essentials

Article Sources and Contributors 26

Article Sources and ContributorsZK Component Development Essentials  Source: http://books.zkoss.org/index.php?title=ZK_Component_Development_Essentials  Contributors: Sphota, Tmillsclare, Tomyeh

ZK Component Overview  Source: http://books.zkoss.org/index.php?title=ZK_Component_Development_Essentials/ZK_Component_Overview  Contributors: Tmillsclare

What is a ZK component  Source: http://books.zkoss.org/index.php?title=ZK_Component_Development_Essentials/ZK_Component_Overview/What_is_a_ZK_component  Contributors:Tmillsclare, Tomyeh

How does a ZK Component work  Source: http://books.zkoss.org/index.php?title=ZK_Component_Development_Essentials/ZK_Component_Overview/How_does_a_ZK_Component_work Contributors: Tmillsclare

Development Tools  Source: http://books.zkoss.org/index.php?title=ZK_Component_Development_Essentials/ZK_Component_Overview/Development_Tools  Contributors: Tomyeh

Creating a simple ZK Component  Source: http://books.zkoss.org/index.php?title=ZK_Component_Development_Essentials/Creating_a_simple_ZK_Component  Contributors: Tmillsclare

ZK's JavaScript Extension  Source: http://books.zkoss.org/index.php?title=ZK_Component_Development_Essentials/Creating_a_simple_ZK_Component/ZK%27s_JavaScript_Extension Contributors: Tmillsclare

Implementing the Component  Source: http://books.zkoss.org/index.php?title=ZK_Component_Development_Essentials/Creating_a_simple_ZK_Component/Implementing_the_Component Contributors: Tmillsclare

Implementing a Component Property  Source:http://books.zkoss.org/index.php?title=ZK_Component_Development_Essentials/Creating_a_simple_ZK_Component/Implementing_the_Component/Implementing_a_Component_Property Contributors: Jimmyshiau, Tmillsclare

Render All Properties to the Client  Source:http://books.zkoss.org/index.php?title=ZK_Component_Development_Essentials/Creating_a_simple_ZK_Component/Implementing_the_Component/Render_All_Properties_to_the_Client Contributors: Tmillsclare

Putting it all Together  Source:http://books.zkoss.org/index.php?title=ZK_Component_Development_Essentials/Creating_a_simple_ZK_Component/Implementing_the_Component/Putting_it_all_Together  Contributors:Tmillsclare

Implementing the Widget  Source: http://books.zkoss.org/index.php?title=ZK_Component_Development_Essentials/Creating_a_simple_ZK_Component/Implementing_the_Widget Contributors: Tmillsclare

Implementing a Widget Property  Source:http://books.zkoss.org/index.php?title=ZK_Component_Development_Essentials/Creating_a_simple_ZK_Component/Implementing_the_Widget/Implementing_a_Widget_Property Contributors: Tmillsclare

Putting it all Together  Source:http://books.zkoss.org/index.php?title=ZK_Component_Development_Essentials/Creating_a_simple_ZK_Component/Implementing_the_Widget/Putting_it_all_Together  Contributors:Jumperchen, Tmillsclare

Rendering Widgets  Source: http://books.zkoss.org/index.php?title=ZK_Component_Development_Essentials/Creating_a_simple_ZK_Component/Rendering_Widgets  Contributors:Tmillsclare

Implementing Molds  Source: http://books.zkoss.org/index.php?title=ZK_Component_Development_Essentials/Creating_a_simple_ZK_Component/Rendering_Widgets/Implementing_Molds Contributors: Jumperchen, Tmillsclare

The Redraw Method  Source: http://books.zkoss.org/index.php?title=ZK_Component_Development_Essentials/Creating_a_simple_ZK_Component/Rendering_Widgets/The_Redraw_Method Contributors: Tmillsclare

Creating the Configuration Files  Source: http://books.zkoss.org/index.php?title=ZK_Component_Development_Essentials/Creating_the_Configuration_Files  Contributors: Tmillsclare

The language-addon  Source: http://books.zkoss.org/index.php?title=ZK_Component_Development_Essentials/Creating_the_Configuration_Files/The_language-addon  Contributors:Tmillsclare, Tomyeh, Tonyq

The Widget Package Descriptor  Source: http://books.zkoss.org/index.php?title=ZK_Component_Development_Essentials/Creating_the_Configuration_Files/The_Widget_Package_Descriptor Contributors: Tmillsclare, Tomyeh

Handling Events  Source: http://books.zkoss.org/index.php?title=ZK_Component_Development_Essentials/Handling_Events  Contributors: Tmillsclare

How we Implement the Event  Source: http://books.zkoss.org/index.php?title=ZK_Component_Development_Essentials/Handling_Events/How_we_Implement_the_Event  Contributors:Tmillsclare

Overriding bind and unbind  Source:http://books.zkoss.org/index.php?title=ZK_Component_Development_Essentials/Handling_Events/How_we_Implement_the_Event/Overriding_bind_and_unbind  Contributors: Tmillsclare

Registering Appropriate Listeners  Source:http://books.zkoss.org/index.php?title=ZK_Component_Development_Essentials/Handling_Events/How_we_Implement_the_Event/Registering_Appropriate_Listeners  Contributors: Tmillsclare

Client-Server Communication  Source: http://books.zkoss.org/index.php?title=ZK_Component_Development_Essentials/Handling_Events/Client-Server_Communication  Contributors:Tmillsclare

Server-side Listeners  Source: http://books.zkoss.org/index.php?title=ZK_Component_Development_Essentials/Handling_Events/Server-side_Listeners  Contributors: Tmillsclare

Declaring an Important Event  Source: http://books.zkoss.org/index.php?title=ZK_Component_Development_Essentials/Handling_Events/Declaring_an_Important_Event  Contributors:Tmillsclare

Packing as a Jar  Source: http://books.zkoss.org/index.php?title=ZK_Component_Development_Essentials/Packing_as_a_Jar  Contributors: Char, Flyworld, Tomyeh, TonyQ

Conclusion  Source: http://books.zkoss.org/index.php?title=ZK_Component_Development_Essentials/Conclusion  Contributors: Tmillsclare

Page 29: ZK 5.0.7 Component Development Essentials

Image Sources, Licenses and Contributors 27

Image Sources, Licenses and ContributorsFile:ZKComDevEss_widget_component_application.png  Source: http://books.zkoss.org/index.php?title=File:ZKComDevEss_widget_component_application.png  License: unknown Contributors: TmillsclareFile:ZKComDevEss_button_labels.png  Source: http://books.zkoss.org/index.php?title=File:ZKComDevEss_button_labels.png  License: unknown  Contributors: TmillsclareFile:ZKComDevEss_button_click.png  Source: http://books.zkoss.org/index.php?title=File:ZKComDevEss_button_click.png  License: unknown  Contributors: TmillsclareFile:ZKComDevEss_component_hierarchy.png  Source: http://books.zkoss.org/index.php?title=File:ZKComDevEss_component_hierarchy.png  License: unknown  Contributors: TmillsclareFile:ZKComDevEss_widget_hierarchy.png  Source: http://books.zkoss.org/index.php?title=File:ZKComDevEss_widget_hierarchy.png  License: unknown  Contributors: TmillsclareFile:ZKComDevEss_bind_.png  Source: http://books.zkoss.org/index.php?title=File:ZKComDevEss_bind_.png  License: unknown  Contributors: TmillsclareFile:ZKComDevEss_unbind_.png  Source: http://books.zkoss.org/index.php?title=File:ZKComDevEss_unbind_.png  License: unknown  Contributors: TmillsclareFile:ZKComDevEss_fire_event.png  Source: http://books.zkoss.org/index.php?title=File:ZKComDevEss_fire_event.png  License: unknown  Contributors: TmillsclareFile:Jar_File_summary.jpg  Source: http://books.zkoss.org/index.php?title=File:Jar_File_summary.jpg  License: unknown  Contributors: TonyQFile:Jar_File_configuration1.jpg  Source: http://books.zkoss.org/index.php?title=File:Jar_File_configuration1.jpg  License: unknown  Contributors: TonyQFile:Jar_File_component1.jpg  Source: http://books.zkoss.org/index.php?title=File:Jar_File_component1.jpg  License: unknown  Contributors: TonyQFile:Jar_File_widget1.jpg  Source: http://books.zkoss.org/index.php?title=File:Jar_File_widget1.jpg  License: unknown  Contributors: TonyQFile:Jar_File_static_resources1.jpg  Source: http://books.zkoss.org/index.php?title=File:Jar_File_static_resources1.jpg  License: unknown  Contributors: TonyQ