Envisage ZK 6: The Next Generation Data Binding System"
From Documentation
(new zk bind syntax) |
|||
(43 intermediate revisions by 4 users not shown) | |||
Line 8: | Line 8: | ||
=Introduction= | =Introduction= | ||
− | + | <b><i>ZK Bind</i></b> 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= | =Features= | ||
==A whole new, clean annotation expression== | ==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 | + | *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. |
− | **@bind(...): used to bind data and command | + | **<b>@id(...)</b>: used to idientify a instance's id , ex a view model or a form. |
− | **@converter(...): used to specify | + | **<b>@init(...)</b>: used to init a instance |
− | **@valiator(...): used to specify | + | **<b>@load(...)</b>: used to bind data and command along with parameters for loading data to target |
− | **@ | + | **<b>@save(...)</b>: used to bind data and command along with parameters for saving data. |
+ | **<b>@bind(...)</b>: used to bind data along with parameters for both loading and saving. | ||
+ | **<b>@converter(...)</b>: used to specify converter along with parameters | ||
+ | **<b>@valiator(...)</b>: used to specify validator along with parameters | ||
+ | **<b>@command(...)</b>: used to bind an event to a command along with parameters. | ||
− | ==EL 2.2 | + | ==EL 2.2 flexible expressions== |
− | *ZK Bind | + | *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 bean properties, indexed properties, Map keys seamlessly. | ||
*Bind to component custom attributes automatically. | *Bind to component custom attributes automatically. | ||
*Bind to Spring, CDI, and Seam managed bean automatically. | *Bind to Spring, CDI, and Seam managed bean automatically. | ||
+ | <source lang="xml"> | ||
+ | <image src="@load(vm.person.boy ? 'boy.png' : 'girl.png')"/> | ||
+ | </source> | ||
+ | <source lang="xml"> | ||
+ | <button onClick="@command(vm.add ? 'add' : 'update')" label="@load(vm.add ? 'Add' : 'Update'"/> | ||
+ | </source> | ||
+ | <source lang="xml"> | ||
+ | <button onClick="@command('subscribe')" disabled="@load(empty vm.symbol)" label="Subscribe"/> | ||
+ | </source> | ||
==One way load only data binding== | ==One way load only data binding== | ||
*Load when bean property changes | *Load when bean property changes | ||
− | <source lang=" | + | *Conditional load after/before executing a command |
− | <label value="@ | + | *Multiple conditional load before/after executing different/same commands |
+ | <source lang="xml"> | ||
+ | <label value="@load(vm.person.fullname)"/> | ||
+ | </source> | ||
+ | <source lang="xml"> | ||
+ | <label value="@load(vm.person.firstname, after='update')"/> | ||
</source> | </source> | ||
− | + | <source lang="xml"> | |
− | <source lang=" | + | <label value="@load(vm.person.firstname, before='delete')"/> |
− | <label value="@ | ||
</source> | </source> | ||
− | + | <source lang="xml"> | |
− | <source lang=" | + | <label value="@load(vm.person.firstname, after={'update','delete'})"/> |
− | <label value="@ | ||
</source> | </source> | ||
− | + | <source lang="xml"> | |
− | <source lang=" | + | <label value="@load(vm.person.firstname, after='update') @load(vm.person.message, after='delete'})"/> |
− | <label value="@ | ||
</source> | </source> | ||
==One way save only data binding== | ==One way save only data binding== | ||
*Save when UI component attribute changes | *Save when UI component attribute changes | ||
− | <source lang=" | + | *Multiple save to property of different target beans |
− | <textbox value="@ | + | *Conditional save before/after executing a command |
+ | *Multiple conditional save before/after executing different/same commands | ||
+ | <source lang="xml"> | ||
+ | <textbox value="@save(vm.person.firstname)"/> | ||
</source> | </source> | ||
− | + | <source lang="xml"> | |
− | <source lang=" | + | <textbox value="@save(vm.person.firstname) @save(vm.tmpperson.firstname)"/> |
− | <textbox value="@ | ||
</source> | </source> | ||
− | + | <source lang="xml"> | |
− | <source lang=" | + | <textbox value="@save(vm.person.firstname, before='update')"/> |
− | <textbox value="@ | ||
</source> | </source> | ||
− | + | <source lang="xml"> | |
− | <source lang=" | + | <textbox value="@save(vm.person.firstname, after='delete')"/> |
− | <textbox value="@ | ||
</source> | </source> | ||
− | + | <source lang="xml"> | |
− | <source lang=" | + | <textbox value="@save(vm.selected.firstname, before={'update','add'})"/> |
− | <textbox value="@ | ||
</source> | </source> | ||
==Initial data binding== | ==Initial data binding== | ||
− | * | + | *Loads when UI components are first added into the binding system |
− | <source lang=" | + | <source lang="xml"> |
− | <label value="@ | + | <label value="@init(vm.selected.firstname)"/> |
</source> | </source> | ||
==Two way data binding== | ==Two way data binding== | ||
− | *Short expression | + | *Multiple conditional load and save on different back-end beans before/after executing different/same commands |
− | <source lang=" | + | <source lang="xml"> |
+ | <textbox value="@load(vm.selected.firstname) @save(vm.selected.firstname) @save(vm.newperson.firstname,before='add')"/> | ||
+ | </source> | ||
+ | |||
+ | *Short expression for both save and load bindings without command condition.<ref>@bind(...) is shortcut for "@load(...) @save(...)", and @save is automatically ignored if the property doesn't support it</ref> | ||
+ | <source lang="xml"> | ||
<textbox value="@bind(vm.person.firstname)"/> | <textbox value="@bind(vm.person.firstname)"/> | ||
</source> | </source> | ||
− | + | <blockquote> | |
− | < | + | ---- |
− | < | + | <references/> |
− | </ | + | </blockquote> |
==Bind to any attributes of the UI components== | ==Bind to any attributes of the UI components== | ||
*Bind symmetrically to all attributes of UI components | *Bind symmetrically to all attributes of UI components | ||
− | <source lang=" | + | <source lang="xml"> |
− | + | <textbox value="@bind(vm.symbol)" instant="true"/> | |
− | + | <button disabled="@load(empty vm.symbol)" label="Subscribe" /> | |
− | |||
− | |||
</source> | </source> | ||
Line 94: | Line 111: | ||
*Automatic event listener registration | *Automatic event listener registration | ||
*Simple command name invocation | *Simple command name invocation | ||
− | <source lang=" | + | <source lang="xml"> |
− | <button onClick="@ | + | <button onClick="@command('subscribe')" disabled="@load(empty vm.symbol)" label="Subscribe" /> |
</source> | </source> | ||
Line 102: | Line 119: | ||
*Local variable scope is limited to the container component | *Local variable scope is limited to the container component | ||
*Support index property | *Support index property | ||
− | <source lang=" | + | <source lang="xml"> |
− | <listbox width="300px" model="@ | + | <listbox width="300px" model="@load(vm.albumList)" selectedItem="@bind(vm.selectedAlbum)" vflex="true"> |
<template name="model" var="a"> | <template name="model" var="a"> | ||
− | <listitem label="@ | + | <listitem label="@load(a.title)"/> |
</template> | </template> | ||
</listbox> | </listbox> | ||
Line 114: | Line 131: | ||
*Submit a form in a whole | *Submit a form in a whole | ||
*Conditional save for different commands | *Conditional save for different commands | ||
− | <source lang=" | + | <source lang="xml"> |
− | <grid | + | <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>Title: <textbox value="@bind(fx.title)"/></row> | ||
<row>Artist: <textbox value="@bind(fx.artist)"/></row> | <row>Artist: <textbox value="@bind(fx.artist)"/></row> | ||
Line 121: | Line 138: | ||
<row>Composer: <textbox value="@bind(fx.composer)"/></row> | <row>Composer: <textbox value="@bind(fx.composer)"/></row> | ||
</grid> | </grid> | ||
− | <button onClick="@ | + | <button onClick="@command('add')" label="Add"/> |
+ | <button onClick="@command('update')" label="Update"/> | ||
</source> | </source> | ||
− | == | + | ==Java annotated data dependency tracking== |
− | + | *Controllable load on save | |
− | + | *@NotifyChange to notify property changes | |
− | + | *@DependsOn to specify property change dependency | |
+ | <source lang="java"> | ||
+ | @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; | ||
+ | } | ||
+ | </source> | ||
==Embedded validation cycle== | ==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 | ||
+ | <source lang="xml"> | ||
+ | <textbox value="@save(vm.selected.firstname) @validator('noEmpty')"/> | ||
+ | </source> | ||
+ | <source lang="xml"> | ||
+ | <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> | ||
+ | </source> | ||
==Enhanced converter mechanism== | ==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 | |
+ | <source lang="xml"> | ||
+ | <datebox value="@bind(vm.selected.birthday) @converter('formatedDate', format='yyyy/MM/dd')"/> | ||
+ | </source> | ||
+ | |||
+ | ==org.zkoss.bind.BindComposer== | ||
+ | *Ease UI components, binder, and ViewModel association | ||
+ | *Each binder covers only the applied component tree | ||
+ | *Inter-binder communications | ||
+ | <source lang="xml"> | ||
+ | <window apply="org.zkoss.bind.BindComposer" viewModel="@id('vm') @init('org.zkoss.mvvm.examples.album.AlbumViewModel')"> | ||
+ | ... | ||
+ | </window> | ||
+ | </source> | ||
− | |||
− | |||
− | |||
− | |||
− | |||
==Bind on demand== | ==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== | ==Support seamless MVVM design pattern== | ||
− | + | *Utilize MVVM design pattern to achieve <b><i>separation of data and logic from presentation</i></b> 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 [http://books.zkoss.org/wiki/Small_Talks/2011/October/Hello_ZK_MVVM][http://books.zkoss.org/wiki/Small_Talks/2011/November/MVVM_in_ZK_6_-_Design_your_first_MVVM_page][http://books.zkoss.org/wiki/Small_Talks/2011/November/MVVM_in_ZK_6_-_Design_CRUD_page_by_MVVM_pattern]. | ||
+ | |||
+ | =Download and Resources= | ||
+ | |||
+ | To test out new features please download our latest [http://sourceforge.net/projects/zk1/files/ZK%20Freshly/zk-6.0.0/ freshly builds here]. | ||
− | = | + | {{Template:CommentedSmalltalk_Footer| |
− | + | |name=Potix Corporation | |
+ | }} |
Latest revision as of 07:46, 6 December 2011
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. |