Envisage ZK 6: The Next Generation Data Binding System
From Documentation
Author
Henri Chen, Principal Engineer, Potix Corporation
Henri Chen, Principal Engineer, Potix Corporation
Date
October 21, 2011
October 21, 2011
Version
ZK 6
ZK 6
Introduction
ZK Bind is a whole new data binding system with new specifications and implementations. Based on the experiences learned from databinder 1 and taking into account suggestions and feedback from users and contributors, we have created this easy to use, flexible, feature rich new data binding system in ZK6.
Features
A whole new, clean annotation expression
- Java style annotation expressions in zul: The new ZK annotation is consistent with Java's annotation style. If you know the Java style, you know the ZK Style.
- A set of collaborated annotations: ZK Bind uses a set of annotations to make the use of data binding as intuitive and clear as possible.
- @id(...): used to idientify a instance's id , ex a view model or a form.
- @init(...): used to init a instance
- @load(...): used to bind data and command along with parameters for loading data to target
- @save(...): used to bind data and command along with parameters for saving data.
- @bind(...): used to bind data along with parameters for both loading and saving.
- @converter(...): used to specify converter along with parameters
- @valiator(...): used to specify validator along with parameters
- @command(...): used to bind an event to a command along with parameters.
EL 2.2 flexible expressions
- ZK Bind accepts EL 2.2 syntax expressions in which you can provide flexible operations easily.
- Bind to bean properties, indexed properties, Map keys seamlessly.
- Bind to component custom attributes automatically.
- Bind to Spring, CDI, and Seam managed bean automatically.
<image src="@load(vm.person.boy ? 'boy.png' : 'girl.png')"/>
<button onClick="@command(vm.add ? 'add' : 'update')" label="@load(vm.add ? 'Add' : 'Update'"/>
<button onClick="@command('subscribe')" disabled="@load(empty vm.symbol)" label="Subscribe"/>
One way load only data binding
- Load when bean property changes
- Conditional load after/before executing a command
- Multiple conditional load before/after executing different/same commands
<label value="@load(vm.person.fullname)"/>
<label value="@load(vm.person.firstname, after='update')"/>
<label value="@load(vm.person.firstname, before='delete')"/>
<label value="@load(vm.person.firstname, after={'update','delete'})"/>
<label value="@load(vm.person.firstname, after='update') @load(vm.person.message, after='delete'})"/>
One way save only data binding
- Save when UI component attribute changes
- Multiple save to property of different target beans
- Conditional save before/after executing a command
- Multiple conditional save before/after executing different/same commands
<textbox value="@save(vm.person.firstname)"/>
<textbox value="@save(vm.person.firstname) @save(vm.tmpperson.firstname)"/>
<textbox value="@save(vm.person.firstname, before='update')"/>
<textbox value="@save(vm.person.firstname, after='delete')"/>
<textbox value="@save(vm.selected.firstname, before={'update','add'})"/>
Initial data binding
- Loads when UI components are first added into the binding system
<label value="@init(vm.selected.firstname)"/>
Two way data binding
- Multiple conditional load and save on different back-end beans before/after executing different/same commands
<textbox value="@load(vm.selected.firstname) @save(vm.selected.firstname) @save(vm.newperson.firstname,before='add')"/>
- Short expression for both save and load bindings without command condition.[1]
<textbox value="@bind(vm.person.firstname)"/>
- ↑ @bind(...) is shortcut for "@load(...) @save(...)", and @save is automatically ignored if the property doesn't support it
Bind to any attributes of the UI components
- Bind symmetrically to all attributes of UI components
<textbox value="@bind(vm.symbol)" instant="true"/>
<button disabled="@load(empty vm.symbol)" label="Subscribe" />
Event command binding
- Bridge ZK event to command
- Automatic event listener registration
- Simple command name invocation
<button onClick="@command('subscribe')" disabled="@load(empty vm.symbol)" label="Subscribe" />
Template/Collection binding
- Binding on Listbox/Grid/Tree/Combobox
- Local variable scope is limited to the container component
- Support index property
<listbox width="300px" model="@load(vm.albumList)" selectedItem="@bind(vm.selectedAlbum)" vflex="true">
<template name="model" var="a">
<listitem label="@load(a.title)"/>
</template>
</listbox>
Form binding
- Middle form binding to avoid affecting back-end data beans
- Submit a form in a whole
- Conditional save for different commands
<grid form="@id('fx') @load(vm.selected) @save(vm.selected, before='update') @save(vm.newAlbum, before='add')">
<row>Title: <textbox value="@bind(fx.title)"/></row>
<row>Artist: <textbox value="@bind(fx.artist)"/></row>
<row><checkbox checked="@bind(fx.classical)"/> Classical</row>
<row>Composer: <textbox value="@bind(fx.composer)"/></row>
</grid>
<button onClick="@command('add')" label="Add"/>
<button onClick="@command('update')" label="Update"/>
Java annotated data dependency tracking
- Controllable load on save
- @NotifyChange to notify property changes
- @DependsOn to specify property change dependency
@NotifyChange //notify firstname change
public void setFirstname(String fn) {
firstname = fn;
}
@NotifyChange //notify lastname change
public void setLastname(String ln) {
lastname = ln;
}
@DependsOn({"firstname","lastname"}) //full name will change if either firstname and/or lastname change
public String getFullname() {
return firstname + " " + lastname;
}
Embedded validation cycle
- Bind validator by name or by EL expression
- Embedded system Validator: provide commonly used validators in which users can use directly by only specifying the name
- Validate a single property or a form
- Validate on a command
<textbox value="@save(vm.selected.firstname) @validator('noEmpty')"/>
<grid form="@id('fx') @load(vm.selected) @save(vm.selected, before='update') @validator(vm.passwordValidator)">
<row>username<textbox value="@bind(fx.username)"/></row>
<row>password<textbox value="@bind(fx.password)" type="password"/></row>
<row>retype password<textbox value="@bind(fx.retypePassword)" type="password"/></row>
</grid>
Enhanced converter mechanism
- Bind converter by name or by EL expression
- Embedded system Converters: provide commonly used converters in which users can use directly by only specifying the name
<datebox value="@bind(vm.selected.birthday) @converter('formatedDate', format='yyyy/MM/dd')"/>
org.zkoss.bind.BindComposer
- Ease UI components, binder, and ViewModel association
- Each binder covers only the applied component tree
- Inter-binder communications
<window apply="org.zkoss.bind.BindComposer" viewModel="@id('vm') @init('org.zkoss.mvvm.examples.album.AlbumViewModel')">
...
</window>
Bind on demand
- Supports dynamic add/remove bindings by API.
- Attached components with binding annotations are automatically managed by the existing binder if covered.
- Detached components that were managed by a binder are automatically removed from the binding management.
Support seamless MVVM design pattern
- Utilize MVVM design pattern to achieve separation of data and logic from presentation easily.
- UI Design and ViewModel can be implemented independently and in parallel.
- Ability to add new Views or change current Views easily.
- Different Views for different devices with a common ViewModel.
- Allow unit-test ViewModel independently without UI environments.
For details about how to apply MVVM design pattern with ZK Bind, please see this series of Small Talks [1][2][3].
Download and Resources
To test out new features please download our latest freshly builds here.
Comments
Copyright © Potix Corporation. This article is licensed under GNU Free Documentation License. |