Envisage ZK 6: The Next Generation Data Binding System"

From Documentation
(new zk bind syntax)
 
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 our version one data binder and feedbacks from users' and contributors' suggestions, we have created this easy to use, flexible, feature rich new data binding system in ZK6.
+
<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==
*Same Java style annotation expression in zul: The new ZK annotation is consistent with Java's annotation style. If you know the Java style, you know the ZK Style.
+
*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.
 
*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.
**<b>@bind(...)</b>: used to bind data and command along with parameters
+
**<b>@id(...)</b>: used to idientify a instance's id , ex a view model or a form.
**<b>@converter(...)</b>: used  to specify converters along with parameters
+
**<b>@init(...)</b>: used to init a instance
**<b>@valiator(...)</b>: used to specify validators along with parameters
+
**<b>@load(...)</b>: used to bind data and command along with parameters for loading data to target
**<b>@form(...)</b>: used to bind a form.
+
**<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 flexible expressions==
 
==EL 2.2 flexible expressions==
*ZK Bind accept EL 2.2 syntax expression that you can provide flexible operations easily.
+
*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">
 
<source lang="xml">
<image src="@bind(vm.person.boy ? 'boy.png' : 'girl.png')"/>
+
<image src="@load(vm.person.boy ? 'boy.png' : 'girl.png')"/>
 
</source>
 
</source>
 
<source lang="xml">
 
<source lang="xml">
<button onClick="@bind(vm.add ? 'add' : 'update')" label="@bind(vm.add ? 'Add' : 'Update'"/>
+
<button onClick="@command(vm.add ? 'add' : 'update')" label="@load(vm.add ? 'Add' : 'Update'"/>
 
</source>
 
</source>
 
<source lang="xml">
 
<source lang="xml">
<button onClick="@bind('subscribe')" disabled="@bind(empty vm.symbol)" label="Subscribe"/>
+
<button onClick="@command('subscribe')" disabled="@load(empty vm.symbol)" label="Subscribe"/>
 
</source>
 
</source>
  
Line 39: Line 43:
 
*Multiple conditional load before/after executing different/same commands
 
*Multiple conditional load before/after executing different/same commands
 
<source lang="xml">
 
<source lang="xml">
<label value="@bind(load=vm.person.fullname)"/>
+
<label value="@load(vm.person.fullname)"/>
 
</source>
 
</source>
 
<source lang="xml">
 
<source lang="xml">
<label value="@bind(load=vm.person.firstname after 'update')"/>
+
<label value="@load(vm.person.firstname, after='update')"/>
 
</source>
 
</source>
 
<source lang="xml">
 
<source lang="xml">
<label value="@bind(load=vm.person.firstname before 'delete')"/>
+
<label value="@load(vm.person.firstname, before='delete')"/>
 
</source>
 
</source>
 
<source lang="xml">
 
<source lang="xml">
<label value="@bind(load={vm.person.firstname after 'update', vm.person.message after 'delete'})"/>
+
<label value="@load(vm.person.firstname, after={'update','delete'})"/>
 +
</source>
 +
<source lang="xml">
 +
<label value="@load(vm.person.firstname, after='update') @load(vm.person.message, after='delete'})"/>
 
</source>
 
</source>
  
Line 57: Line 64:
 
*Multiple conditional save before/after executing different/same commands
 
*Multiple conditional save before/after executing different/same commands
 
<source lang="xml">
 
<source lang="xml">
<textbox value="@bind(save=vm.person.firstname)"/>
+
<textbox value="@save(vm.person.firstname)"/>
 
</source>
 
</source>
 
<source lang="xml">
 
<source lang="xml">
<textbox value="@bind(save={vm.person.firstname, vm.tmpperson.firstname})"/>
+
<textbox value="@save(vm.person.firstname) @save(vm.tmpperson.firstname)"/>
 
</source>
 
</source>
 
<source lang="xml">
 
<source lang="xml">
<textbox value="@bind(save=vm.person.firstname before 'update')"/>
+
<textbox value="@save(vm.person.firstname, before='update')"/>
 
</source>
 
</source>
 
<source lang="xml">
 
<source lang="xml">
<textbox value="@bind(save=vm.person.firstname after 'delete')"/>
+
<textbox value="@save(vm.person.firstname, after='delete')"/>
 
</source>
 
</source>
 
<source lang="xml">
 
<source lang="xml">
<textbox value="@bind(save={vm.selected.firstname before 'update', vm.newperson.firstname before 'add'})"/>
+
<textbox value="@save(vm.selected.firstname, before={'update','add'})"/>
 
</source>
 
</source>
  
 
==Initial data binding==
 
==Initial data binding==
*Load when UI components are first added into the binding system
+
*Loads when UI components are first added into the binding system
 
<source lang="xml">
 
<source lang="xml">
<label value="@bind(init=vm.selected.firstname)"/>
+
<label value="@init(vm.selected.firstname)"/>
 
</source>
 
</source>
  
 
==Two way data binding==
 
==Two way data binding==
*Short expression of both save and load bindings
 
 
*Multiple conditional load and save on different back-end beans before/after executing different/same commands
 
*Multiple conditional load and save on different back-end beans before/after executing different/same commands
 
<source lang="xml">
 
<source lang="xml">
<textbox value="@bind(vm.person.firstname)"/>
+
<textbox value="@load(vm.selected.firstname) @save(vm.selected.firstname) @save(vm.newperson.firstname,before='add')"/>
 
</source>
 
</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">
 
<source lang="xml">
<textbox value="@bind(load=vm.selected.firstname, save={vm.selected.firstname, vm.newperson.firstname before 'add'})"/>
+
<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==
Line 92: Line 104:
 
<source lang="xml">
 
<source lang="xml">
 
<textbox value="@bind(vm.symbol)" instant="true"/>
 
<textbox value="@bind(vm.symbol)" instant="true"/>
<button onClick="@bind('subscribe')" disabled="@bind(empty vm.symbol)" label="Subscribe" />
+
<button disabled="@load(empty vm.symbol)" label="Subscribe" />
 
</source>
 
</source>
  
Line 100: Line 112:
 
*Simple command name invocation
 
*Simple command name invocation
 
<source lang="xml">
 
<source lang="xml">
<button onClick="@bind('subscribe')" disabled="@bind(empty vm.symbol)" label="Subscribe" />
+
<button onClick="@command('subscribe')" disabled="@load(empty vm.symbol)" label="Subscribe" />
 
</source>
 
</source>
  
Line 108: Line 120:
 
*Support index property
 
*Support index property
 
<source lang="xml">
 
<source lang="xml">
<listbox width="300px" model="@bind(vm.albumList)" selectedItem="@bind(vm.selectedAlbum)" vflex="true">
+
<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="@bind(a.title)"/>
+
         <listitem label="@load(a.title)"/>
 
     </template>
 
     </template>
 
</listbox>
 
</listbox>
Line 120: Line 132:
 
*Conditional save for different commands
 
*Conditional save for different commands
 
<source lang="xml">
 
<source lang="xml">
<grid self="@form(id='fx', load=vm.selected, save={vm.selected before 'update', vm.newAlbum before 'add'})">
+
<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 126: Line 138:
 
     <row>Composer: <textbox value="@bind(fx.composer)"/></row>
 
     <row>Composer: <textbox value="@bind(fx.composer)"/></row>
 
</grid>
 
</grid>
<button onClick="@bind('add')" label="Add"/>
+
<button onClick="@command('add')" label="Add"/>
<button onClick="@bind('update')" label="Update"/>
+
<button onClick="@command('update')" label="Update"/>
 
</source>
 
</source>
  
Line 153: Line 165:
 
==Embedded validation cycle==
 
==Embedded validation cycle==
 
*Bind validator by name or by EL expression
 
*Bind validator by name or by EL expression
*Embedded system Validator: provide commonly used validators that user can use directly by specifying only the name
+
*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 a single property or a form
 
*Validate on a command
 
*Validate on a command
 
<source lang="xml">
 
<source lang="xml">
<textbox value="@bind(save=vm.selected.firstname) @validator('noEmpty')"/>
+
<textbox value="@save(vm.selected.firstname) @validator('noEmpty')"/>
 
</source>
 
</source>
 
<source lang="xml">
 
<source lang="xml">
<grid self="@form(id='fx', load=vm.selected, save=vm.selected before 'update') @validator(vm.passwordValidator)">
+
<grid form="@id('fx') @load(vm.selected) @save(vm.selected, before='update') @validator(vm.passwordValidator)">
 
     <row>username<textbox value="@bind(fx.username)"/></row>
 
     <row>username<textbox value="@bind(fx.username)"/></row>
 
     <row>password<textbox value="@bind(fx.password)" type="password"/></row>
 
     <row>password<textbox value="@bind(fx.password)" type="password"/></row>
Line 169: Line 181:
 
==Enhanced converter mechanism==
 
==Enhanced converter mechanism==
 
*Bind converter by name or by EL expression
 
*Bind converter by name or by EL expression
*Embedded system Converters: provide commonly used converters that user can use directly by specifying only the name
+
*Embedded system Converters: provide commonly used converters in which users can use directly by only specifying the name  
 
<source lang="xml">
 
<source lang="xml">
 
<datebox value="@bind(vm.selected.birthday) @converter('formatedDate', format='yyyy/MM/dd')"/>
 
<datebox value="@bind(vm.selected.birthday) @converter('formatedDate', format='yyyy/MM/dd')"/>
Line 179: Line 191:
 
*Inter-binder communications
 
*Inter-binder communications
 
<source lang="xml">
 
<source lang="xml">
<window apply="org.zkoss.bind.BindComposer" viewModel="@bind(vm='org.zkoss.mvvm.examples.album.AlbumViewModel')">
+
<window apply="org.zkoss.bind.BindComposer" viewModel="@id('vm') @init('org.zkoss.mvvm.examples.album.AlbumViewModel')">
 
     ...
 
     ...
 
</window>
 
</window>
Line 185: Line 197:
  
 
==Bind on demand==
 
==Bind on demand==
*Support dynamically add/remove bindings by API.
+
*Supports dynamic add/remove bindings by API.
 
*Attached components with binding annotations are automatically managed by the existing binder if covered.
 
*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.
 
*Detached components that were managed by a binder are automatically removed from the binding management.
Line 191: Line 203:
 
==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.
 
*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 in parallel independently.
+
**UI Design and ViewModel can be implemented independently and in parallel.
**Can add new Views or change current View easily.
+
**Ability to add new Views or change current Views easily.
**Different views for different devices with a common ViewModel.
+
**Different Views for different devices with a common ViewModel.
 
**Allow unit-test ViewModel independently without UI environments.
 
**Allow unit-test ViewModel independently without UI environments.
  
Line 200: Line 212:
 
=Download and Resources=
 
=Download and Resources=
  
To test out the new features please download one of our latest [http://sourceforge.net/projects/zk1/files/ZK%20Freshly/zk-6.0.0/ freshly builds here].
+
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|
 
{{Template:CommentedSmalltalk_Footer|
 
|name=Potix Corporation
 
|name=Potix Corporation
 
}}
 
}}

Latest revision as of 07:46, 6 December 2011

DocumentationSmall Talks2011OctoberEnvisage ZK 6: The Next Generation Data Binding System
Envisage ZK 6: The Next Generation Data Binding System

Author
Henri Chen, Principal Engineer, Potix Corporation
Date
October 21, 2011
Version
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)"/>

  1. @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.