New Features of ZK 8.0.0

From Documentation
DocumentationSmall Talks2015OctoberNew Features of ZK 8.0.0
New Features of ZK 8.0.0

Author
Timothy Clare, Hawk Chen, Potix Corporation
Date
Oct. 6, 2015
Version
ZK 8.0.0


Introduction

The ZK team is proud to announce the release of ZK 8!

ZK 8's main focus is on providing developers with even more powerful tools, allowing faster and more accurate development of Java Web Applications. We are proud to announce the extensive improvement to EL, now supporting EL3, major MVVM enhancements, and many more changes.

To understand why you need ZK 8, and how it helps you to stay true to your Java roots, but also effortlessly keep up with the ever-evolving world of front-end technologies, read ZK 8 Philosophy


Download and Demo




Shadow Elements

  • Available for ZK:
  • http://www.zkoss.org/product/zkhttp://www.zkoss.org/whyzk/zkeeVersion ee.png

ZK 8 introduces a new concept called Shadow Element.

In simple terms, shadow elements help application developers compose an html layout with some dynamic data. They are basically templates; however, with shadow elements, applications could manage templates and their implementation even when they are outside of the component tree. Thus, a shadow element is not visible to users, as it is handled by ZK.

A web designer can pre-define a template based on HTML syntax for application developers to use.

For example,

<div>
    <if test="${user.editable}">
        User Name: <textbox value="${user.name}"/>
        <forEach items="${user.phones}" var="phone">
            <label value="${phone.number}"/>
        </forEach>
    </if>
</div>

Shadow Diagram.PNG

As shown in the diagram above, the tree is separated into two parts - Logical Tree and Composed Tree.

  • Logical Tree is created by ZK page parser to construct a page definition tree and then instantiate it into a "Composed Tree".
  • Composed Tree is also separated into two parts, one is the component tree (green area) which is the same as before, and the other is the new concept (red area) shadow tree, which is not visible for application developers but component developers.

The shadow tree in the example above with EL expression won't be alive once the output is rendered to the client. This is because shadow elements are not applied with dynamic data such as @load expressions, so there is no reason to store them in the server side to burden the memory consumption.


Example

To give an example of the power available, the following demo outlines an application using 3 dataviews (grid, list and tree) using the same dataset and codebase.


To fully understand the power of shadow components, please refer to the ZK 8 Series Smalltalk.

Use Shadow Elements in MVC

We've listened to your feedback! Many of you would like to also incorporate this shadow feature in your MVC projects. Therefore, ShadowTemplate and CollectionTemplate are now introduced, allowing you to apply shadow elements and templates dynamically in MVC-based Java class.

For more information, please refer to ZK_Developer's Reference/UI Composing/Shadow for MVC.

Major MVVM Enhancements

Performance Improvements

  • Available for ZK:
  • http://www.zkoss.org/product/zkhttp://www.zkoss.org/whyzk/zkeeVersion ce-pe-ee.png

ZK 8 has improved a lot of performance on both the client and the server side, especially for MVVM, it now has a lower memory consumption and a shorter response time.

Memory Consumption

ZK8 performance test memory consumption.png

Response Time

ZK8 performance test response time.png

Summary

Shadow Element

  1. More lightweight and more efficient in supporting a collection data binding.
  2. Auto-releases the memory once it no longer contains dynamical data attributes.

EE specific

  1. Uses a merge algorithm to reduce the MVVM tracking nodes.
  2. Speeds up Bind EL expression resolving.


If you would like to reproduce the testing, please refer to Small Talks/2015/September/Faster And Lighter, The Performance Test On ZK8 for details.

SmartNotifyChange

  • Available for ZK:
  • http://www.zkoss.org/product/zkhttp://www.zkoss.org/whyzk/zkeeVersion ce-pe-ee.png


ZK 8 brings about a change to the notify system.You are all used to @NotifyChange; however, ZK 8 has a better way, @SmartNotifyChange. Its usage is essentially the same as @NotifyChange, except it will only notify the binder when a value has changed, unlike @NotifyChange. Thus it is capable of a better performance.

The following shows some example code:

public class OrderVM {

    //other code...

    //action command
    @SmartNotifyChange({"selected","orders","messages"})
    @Command
    public void newOrder(){
        Order order = new Order();
        getOrders().add(order); //add new order to order list
        selected = order;//select the new one
    }
}

For more information, please consult the ZK MVVM Reference and the new form binding blog.

MVVM support at the client

  • Available for ZK:
  • http://www.zkoss.org/product/zkhttp://www.zkoss.org/whyzk/zkeeVersion ce-pe-ee.png


After listening to all your feedback, the ZK team has introduced functionality in ZK 8 which allows developers to access ViewModel properties at the client. The following couple of code snippets demonstrates how to use this functionality.

Publishing a command using native component or direct invocation

<xhtml:button n:onClick="@command('doClick', {key:value, key1:value1})"/>
wgt.$binder().command('doClick', args);

Subscribing to commands

wgt.$binder().after('commandName', callbackFuncation);

For more information, please take a look at the ZK 8 Series Smalltalk.

BindingParam annotation supports converting from JSON to POJO automatically

  • Available for ZK:
  • http://www.zkoss.org/product/zkhttp://www.zkoss.org/whyzk/zkeeVersion ee.png


ZK 8 now supports the ability to convert JSON sent to ZK into objects at the server automatically. Consider this example.

zkbind.$(someone).command('dataChange', {data:{title: "myData"}});

The above code will send JSON data to the command function "dataChange"; this can be automatically converted into an appropriate object using the BindingParam.

public static class DataObject {
	private String title;
	public void setTitle(String title) {
		this.title = title;
	}
	public String getTitle() {return title;}
}

@Command
public void dataChange(@BindingParam("data") DataObject data) {
	// do something here.
}

For more information, please visit ZK Configuration Reference.

Children binding supports list model

  • Available for ZK:
  • http://www.zkoss.org/product/zkhttp://www.zkoss.org/whyzk/zkeeVersion ce-pe-ee.png


In ZK 8, children binding supports a ListModel! This means you can separate the View and Model by implementing ListModel, which is used to provide data. Additionally, when you add/update/remove the data in the model, the corresponding components in children binding will be re-rendered at the same time.

When using List in children binding, to update data you have to use @NotifyChange to notify the binder of any property changes, and the whole rendered components in children binding will be re-rendered at the same time.

The following example outlines the usage:

<vlayout children="@load(vm.model)">
  <template name="children">
  ...
  </template>
</vlayout>
private ListModelList model = new ListModelList();
...

@Command
public void add_model() {
  Product newProduct = new Product(++count, "Microwave oven", 999);
  model.add(newProduct);
}

For more information, please take a look at our blog series on ZK 8 data binding.

FormattedTimeConverter introduced

  • Available for ZK:
  • http://www.zkoss.org/product/zkhttp://www.zkoss.org/whyzk/zkeeVersion ce-pe-ee.png


ZK 8 introduces a new converter named formattedTime. This makes it extremely easy to output a specific time using a specified format. The following shows an example of usage:

<label value="@load(item.time) @converter('formattedTime', format='hhmmss')"/>

For more information, please refer to refer to our ZK MVVM Reference.

New components & enhancements

Lightweight rich editor

  • Available for ZK:
  • http://www.zkoss.org/product/zkhttp://www.zkoss.org/whyzk/zkeeVersion ee.png

ZK 8 introduces a brand new lightweight component called Tbeditor, which represents the JavaScript component Trumbowyg. Tbeditor is a rich WYSIWYG text editor.

The following is an example of using Tbeditor in your application.

Zkcompref tbeditor.png

<tbeditor id="tb" value="this is a demo for &lt;b&gt;trumbowy&lt;/b&gt; editor!!" />

For more information, please consult the ZK Component Reference.

Timepicker Component

  • Available for ZK:
  • http://www.zkoss.org/product/zkhttp://www.zkoss.org/whyzk/zkeeVersion ee.png

ZK 8 introduces a new component to handle times. This component also has a lot of functionalities, such as minimum & maximum times, along with formatting.

ZKCompRef Timepicker.png


 <window title="Simple" width="300px" border="normal">
     <timebox id="tb0"/>
 </window>

For more information, please consult the ZK Component Reference.

Scrollview component

  • Available for ZK:
  • http://www.zkoss.org/product/zkhttp://www.zkoss.org/whyzk/zkeeVersion ee.png


The Scrollview component, first introduced in ZK 6.5 with mobile and tablet compatibility, is now also available on desktop. With the amazing infinite scrolling feature.

For example,

<zscript><![CDATA[
public void append(Scrollview sv, int pos, boolean outBound) {
	if (outBound && pos > 0) {
		Window w = new Window("window end", "normal", false);
		sv.appendChild(w);
	}
}
]]></zscript>
<scrollview id="sv" onScroll="append(self, event.pos, event.outOfBound)" orient="horizontal">
	<window title="window1" border="normal">
            This is Window 1
        </window>
</scrollview>

With that, users can scroll down endlessly.

Just like in the 6.5 version, this component also provides two events.

  • onScroll
  • onScrolling

The only difference is that in ZK 8.0, the onScroll event will be triggered when users scroll all the way to the top or to the end of the page. The onScrolling event remains the same as before.


For more information, please consult the ZK Component Reference.

Rowlayout

  • Available for ZK:
  • http://www.zkoss.org/product/zkhttp://www.zkoss.org/whyzk/zkeeVersion ee.png

ZK 8 introduces a new, powerful layout component named rowlayout which allows developers to place components inside a grid. This allows for flexible and simple layouts. The following diagram illustrates the rowlayout/rowchildren components and their various configurable parameters.

ZKComRef Rowlayout.PNG

Using rowlayout component is simple. First, use rowlayout to divide the horizontal space of its parent container into a number of columns. You also have the option of specifying the column/spacing ratio. The default number of columns is 12, and the default column/spacing ratio is 1/3, which means the column is 3 times wider than the spacing between columns. Spacing could be given as a ratio, a percentage or a floating-point number.

A sample usage is demonstrated below:

<rowlayout ncols="12" spacing="1/3">
	<rowchildren colspan="3" offset="2">
	</rowchildren>
</rowlayout>

For more information, please consult the ZK Component Reference.

Support Expression Language 3 (EL3)

  • Available for ZK:
  • http://www.zkoss.org/product/zkhttp://www.zkoss.org/whyzk/zkeeVersion ce-pe-ee.png

ZK 8 introduces the new generation expression language of Java EE 7 – Expression Language 3 (EL 3). Now we can do more complicated and more powerful things with the newer expression language. There are many new features in EL 3 such as new operators, lambda expressions, and collection operations. For more information on EL3, please take a look at the specification, JSR-341.

Please note that EL3 and all its features (including Lambda expressions) work for JDK 5 and above in ZK framework.

Lambda Expressions

Each converter is implemented with the capability to interpret lambda expressions defined in zul. The following code shows a textbox whose value and onOK attribute are both driven by lambdas.

<textbox value="@load((x -> (x * 100) / 2.54)(vm.value))" 
    onOK="@command('click', key=((x -> (x * 2.54) / 100)(self.value)))" />

The syntax used is the same as the ones in Java SE 8 and behaves like an anonymous function which is discarded after evaluation. We can name a lambda and evaluate indirectly.

Take the lambda expression (x -> (x * 100) / 2.54)for example. In this case, it will create an anonymous function which takes a value, multiplies it by 100 and divides the result by 2.54. This function is then applied to vm.value, where vm stands for our ViewModel.

To simplify this, let us write some pseudo code for demonstration purposes.

myFunction = x -> (x * 100) / 2.54 //assign a lambda to myFunction temporarily
myFunction(vm.value) //execute myFunction passing vm.value as the parameter

While the above is just pseudo code to help you understand the functionality better, it does demonstrate naming of lambdas, which is also possible. The following section outlines the steps of achieving this by using two new operators.

New Operators

String Concatenation

String concatenation has been introduced to make it easy to construct strings within EL expressions. The following code snippet demonstrates how to do so.

<label value="@load(('Hi, ' += vm.firstname += ' ' += vm.lastname))" />

Assignment and Semicolons

Both assignment and semicolon operators are now implemented. Below shows an example of both being used.

<label value="@load((incr = x -> x + 1; incr(5)))" />

The assignment operator in this instance assigns a lambda function to incr which takes x, increments by 1 and then returns it.

incr = x -> x + 1

By using the ';' operator, it evaluates the left-hand side first; thus, creating a lambda function incr, as previously discussed. Then, it evaluates and returns the right-hand side. So in the following case:

<label value="@load((incr = x -> x + 1; incr(5)))" />

The value assigned to the label would be 6, as the lambda function is first evaluated and assigned to incr, then the incr(5) call is evaluated leading to a return value of 6.


Collection Operations

In ZK 8 it is now possible to use collection chain operations directly. In the example below we turn vm.names into stream() and then can create a pipeline of commands.

<listbox model="@load((vm.names.stream()
                               .filter(x -> x.contains(vm.filter))
                               .toList()))">

In addition to pipelines, ZK 8's EL 3 supports easy collection construction using brackets ([ ]). The following example demonstrates this.

<label value="@load(([1, 2, 3, 4].stream().sum()))" />

Static Field and Method References

You can reference a Java class' static field or static method with the syntax Classname.Field, such as

	
<label value="@load((Math.sqrt(16)))" />

Please note that java.lang.* is imported by default.

Custom data attribute handlers are now possible

  • Available for ZK:
  • http://www.zkoss.org/product/zkhttp://www.zkoss.org/whyzk/zkeeVersion ce-pe-ee.png


It is possible to define custom data-handlers for client attributes, which gives extra flexibility to developers looking to integrate and use 3rd party libraries.

For example, the following demonstrates a data-handler for jQuery's mask functionality.


Zul File:

<textbox xmlns:ca="client/attribute" ca:data-mask="00:00:00" onChange='Clients.log(self.value)'/>

zk.xml:

<client-config>	
	<data-handler>
		<name>mask</name><!-- the attribute name, i.e. data-mask -->
		<depends>http://igorescobar.github.io/jQuery-Mask-Plugin/js/jquery.mask.min.js</depends>
		<script>
		function (wgt, dataValue) {
			jq(wgt.$n()).mask(dataValue);

			// unformat after onChange event.
			wgt.listen({onChange: function (event) {
				event.data.value = jq(this.$n()).cleanVal();
			}});
		}
		</script>
	</data-handler>
</client-config>

For more information, please refer to the ZK8: Simple but Powerful; Using Data-handler API to Work with Front-End Technologies.

Font Awesome upgrade

  • Available for ZK:
  • http://www.zkoss.org/product/zkhttp://www.zkoss.org/whyzk/zkeeVersion ce-pe-ee.png


Font awesome has been upgraded to version 4.3, introducing over 40 new icons. For more details, please check the font-awesome website.

Introducing Danish language support

  • Available for ZK:
  • http://www.zkoss.org/product/zkhttp://www.zkoss.org/whyzk/zkeeVersion ce-pe-ee.png

Thanks to our contributor Flemming Birch-Rasmussen, ZK 8 now provides support in Danish.

Websocket Support

Provide Storage, ZKWebSocket, and Command to share data and communicate between a ZK application and a websocket application within the same session. We can now receive the data storage from ZK desktop object to share or update the application data, so that the websocket echo server can use or get the latest data from it or vice versa. This makes it possible to embrace big data in the most efficient manner.

Please refer to ZK_Developer's Reference/Integration/Miscellenous/Websocket_Channel

Performance Improvement

In addition to the performance boost brought by MVVM enhancements, the following efforts have been made in ZK 8 to further advance the overall performance and usability.

  1. More efficient rendering on children binding.
  2. Use a direct method invoking instead of java reflection for component to apply properties.
  3. Use a lazy initialization of Java Object creation to reduce the memory footprint.
  4. Use StringBuilder instead of StringBuffer for component rendering.
  5. Use new string escape implementation.
  6. Use java.util.concurrent framework instead of synchronised keyword.

These optimizations may bring as much as 50% of saved memory and 75% of shortened response time. See also #Major MVVM Enhancements for details and test cases.

Other changes

ZHTML component's src attribute supports encoded url in ZUL

  • Available for ZK:
  • http://www.zkoss.org/product/zkhttp://www.zkoss.org/whyzk/zkeeVersion ce-pe-ee.png

ZK 8's ZHTML components now support encoded urls, making it much easier to specify images and other urls on the src attribute.

For example:

<x:img xmlns:x="xhtml" src="~./img/spacer.gif" xmlns:c="client" c:onBind='zk.log(this.$n().src)'/>

For more information, please refer to the ZK Component Reference.

ZHTML supports dynamic data binding

  • Available for ZK:
  • http://www.zkoss.org/product/zkhttp://www.zkoss.org/whyzk/zkeeVersion ce-pe-ee.png


The textContent attribute now supports dynamic databinding, making it possible to use MVVM based commands for a textContent attribute. For example:

<label textContent="@load(each.author.name)"
	sclass="author-name z-label" />

Simplified thrown exceptions

  • Available for ZK:
  • http://www.zkoss.org/product/zkhttp://www.zkoss.org/whyzk/zkeeVersion ce-pe-ee.png

Exceptions were thrown as UIExceptions and when including templates or similar procedures, the resulting stacktrace was exceptionally hard to follow. This also makes it difficult to create meaningful error pages for application.

With the advent of ZK 8, exceptions are are no longer wrapped with UIException; they will throw a RuntimeException.

Multiple constraints can have its own error message

  • Available for ZK:
  • http://www.zkoss.org/product/zkhttp://www.zkoss.org/whyzk/zkeeVersion ce-pe-ee.png

Before, when defining constraints, only the last constraint could have a separate error message. This has now been rectified and every constraint can have its own custom error message.

For example:

<datebox constraint="no empty: please select a date; no future: now or never" />

For more information, please refer to ZK's Component Reference.

Datebox calendar now contains a today button

  • Available for ZK:
  • http://www.zkoss.org/product/zkhttp://www.zkoss.org/whyzk/zkeeVersion ce-pe-ee.png

In ZK 8, the Datebox calendar now contains a button that makes it easy to reset the date to today. The button assumes the form of the current date.

ZKComRef Datebox Link Of Today.PNG

Embedded types now allowed

  • Available for ZK:
  • http://www.zkoss.org/product/zkhttp://www.zkoss.org/whyzk/zkeeVersion ce-pe-ee.png

When parsing a page, sometimes an error would occur when HTML was embedded in a ZHTML page. This is now fixed and the ability to use different parsers, depending on the syntax in the page, is allowed.

For example, here we have HTML embedded inside ZHTML:

<html>
	<head>
		 <!--[if lte IE 9]>
			<link rel="stylesheet" href="../assets/css/test.min.css" />
		<![endif]-->
	</head>
<body>
<u:window xmlns:u="zul" title="test" id="mainWindow" apply="org.zkoss.bind.BindComposer"
	viewModel="@id('vm') @init('test.MyVM')" height="100%" width="100%">
	&copy Test
</u:window>
</body>
</html>

ForeachStatus is consistent with JSTL's varStatus properties

  • Available for ZK:
  • http://www.zkoss.org/product/zkhttp://www.zkoss.org/whyzk/zkeeVersion ce-pe-ee.png

ZK's ForEachStatus now has the same properties as varStatus, so it is more intuitive for developers to use what they are used to as is.

<zk xmlns:n="native">
	<n:h4>1. Test case: forEach="one, two, three, four"</n:h4>
	<zscript>
	items = Arrays.asList(new Object[] { "one", "two", "three", "four" });
</zscript>
	<div style="border:1px solid blue">
		<div forEach="${items}">
			${each} Index: ${forEachStatus.index} Count:
			${forEachStatus.count} First: ${forEachStatus.first} Last:
			${forEachStatus.last}
		</div>
	</div>
	Result:
	<div style="border:1px solid red;color:blue">
		<div>one Index: 0 Count: 1 First: true Last: false</div>
		<div>two Index: 1 Count: 2 First: false Last: false</div>
		<div>three Index: 2 Count: 3 First: false Last: false</div>
		<div>four Index: 3 Count: 4 First: false Last: true</div>
	</div>
	<n:h4>2. Test case: forEach="one, two, three, four" forEachStep="3"</n:h4>
	<div style="border:1px solid blue">
		<div forEach="${items}" forEachStep="3">
			${each} Index: ${forEachStatus.index} Count:
			${forEachStatus.count} First: ${forEachStatus.first} Last:
			${forEachStatus.last}
		</div>
	</div>
	Result:
	<div style="border:1px solid red;color:blue">
		<div>one Index: 0 Count: 1 First: true Last: false</div>
		<div>four Index: 3 Count: 2 First: false Last: true</div>
	</div>
	<n:h4>3. Test case: forEach="one, two, three, four" forEachBegin="1" forEachStep="3"
	</n:h4>
	<div style="border:1px solid blue">
		<div forEach="${items}" forEachBegin="1" forEachStep="3">
			${each} Index: ${forEachStatus.index} Count:
			${forEachStatus.count} First: ${forEachStatus.first} Last:
			${forEachStatus.last}
		</div>
	</div>
	Result:
	<div style="border:1px solid red;color:blue">
		<div>two Index: 1 Count: 1 First: true Last: true</div>
	</div>
</zk>

Customizable upload error message

When the file size exceeds the maximum size limit for upload, you may wish to display a message to alert your user. Now you can customize the message based on your preferences. Please refer to ZK Developer's Reference/Internationalization.

For Example, (in WEB-INF/zk-label.properties)

MZul.2105=The request was rejected because its size ({0}) exceeds the configured maximum ({1})

Notice that you can change the index {0} and {1} to choose the file size unit. (Auto:{0},{1} Byte:{2},{3} KB:{4},{5} MB:{6},{7})

Usability enhancements

The following changes are made to prevent you from doing it wrong and getting unexpected behaviors.

Auxheader doesn't allow you to set its size by width/height/hflex/vflex

Because an Auxheader's width and height are automatically determined by its column span and the row span, we now forbid users to set the width and height to avoid any confusion and unexpected behavior.

Width/height should not be set at the same time as hflex/vflex

Width and hflex are both for determining the width of a component; therefore, it makes no sense to apply both the width attribute and the hflex attribute on the same component at the same time. In ZK 8, an exception will be thrown if a component is assigned with both the width and the hflex attribute to avoid confusion. This also applies to the case where height and vflex are set to the same component.

Comments



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