Envisage ZK 6: The Next Generation Data Binding System"

From Documentation
(new zk bind syntax)
 
(37 intermediate revisions by 4 users not shown)
Line 8: Line 8:
  
 
=Introduction=
 
=Introduction=
This 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 cooked this easy to use, flexible, features 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. For details, please refer to [link].
+
*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 use a set of annotations to make using 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.
**@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 converters along with parameters
+
**<b>@init(...)</b>: used to init a instance
**@valiator(...): used to specify validators along with parameters
+
**<b>@load(...)</b>: used to bind data and command along with parameters for loading data to target
**@form(...): 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 flexiable 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">
 +
<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="java">
+
*Conditional load after/before executing a command
<label value="@bind(load=vm.person.fullname)"/>
+
*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>
*Conditional load after executing command
+
<source lang="xml">
<source lang="java">
+
<label value="@load(vm.person.firstname, before='delete')"/>
<label value="@bind(load=vm.person.firstname after 'update')"/>
 
 
</source>
 
</source>
*Conditional load before executing command
+
<source lang="xml">
<source lang="java">
+
<label value="@load(vm.person.firstname, after={'update','delete'})"/>
<label value="@bind(load=vm.person.firstname before 'delete')"/>
 
 
</source>
 
</source>
*Multiple conditional load before/after different/same commands
+
<source lang="xml">
<source lang="java">
+
<label value="@load(vm.person.firstname, after='update') @load(vm.person.message, after='delete'})"/>
<label value="@bind(load={vm.person.firstname after 'update', vm.person.message after 'delete'})"/>
 
 
</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="java">
+
*Multiple save to property of different target beans
<textbox value="@bind(save=vm.person.firstname)"/>
+
*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>
*Multiple save to property of different target beans
+
<source lang="xml">
<source lang="java">
+
<textbox value="@save(vm.person.firstname) @save(vm.tmpperson.firstname)"/>
<textbox value="@bind(save={vm.person.firstname, vm.tmpperson.firstname})"/>
 
 
</source>
 
</source>
*Conditional save before executing command
+
<source lang="xml">
<source lang="java">
+
<textbox value="@save(vm.person.firstname, before='update')"/>
<textbox value="@bind(save=vm.person.firstname before 'update')"/>
 
 
</source>
 
</source>
*Conditional save after  executing command
+
<source lang="xml">
<source lang="java">
+
<textbox value="@save(vm.person.firstname, after='delete')"/>
<textbox value="@bind(save=vm.person.firstname after 'delete'"/>
 
 
</source>
 
</source>
*Multiple conditional save before/after executing different/same commands
+
<source lang="xml">
<source lang="java">
+
<textbox value="@save(vm.selected.firstname, before={'update','add'})"/>
<textbox value="@bind(save={vm.selected.firstname before 'update', vm.newperson.firstname before '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="java">
+
<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
<source lang="java">
+
<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>
*Load and save on different target beans
+
<blockquote>
<source lang="java">
+
----
<textbox value="@bind(load=vm.selected.firstname, save={vm.selected.firstname, vm.newperson.firstname before 'add'})"/>
+
<references/>
</source>
+
</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="java">
+
<source lang="xml">
<hlayout>
+
<textbox value="@bind(vm.symbol)" instant="true"/>
    <textbox value="@bind(vm.symbol)" instant="true"/>
+
<button disabled="@load(empty vm.symbol)" label="Subscribe" />
    <button onClick="@bind('subscribe')" disabled="@bind(empty vm.symbol)" label="Subscribe" />
 
</hlayout>
 
 
</source>
 
</source>
  
Line 94: Line 111:
 
*Automatic event listener registration
 
*Automatic event listener registration
 
*Simple command name invocation
 
*Simple command name invocation
<source lang="java">
+
<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 103: 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 115: 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 on 'update', vm.newAlbum on '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 121: 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="@command('update')" label="Update"/>
 
</source>
 
</source>
  
==Automatic Java annotated data dependency tracking==
+
==Java annotated data dependency tracking==
 
*Controllable load on save
 
*Controllable load on save
 
*@NotifyChange to notify property changes
 
*@NotifyChange to notify property changes
Line 146: Line 164:
  
 
==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 specify 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 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
+
*Bind converter by name or by EL expression
*Embedded system Converters: provide commonly used converters that user can use directly by specify the name
+
*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>
  
==GenericBindComposer==
 
*Ease UI component tree, binder, and data source association
 
*Each binder covers only the applied component tree
 
*Inter-BindComposer communications
 
 
 
==Bind on demand==
 
==Bind on demand==
*Support dynamically add/remove bindings by API.
+
*Supports dynamic add/remove bindings by API.
*Attatched 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 management.
+
*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==
*You can now utilize MVVM design pattern to achieve "separation of data and logic from presentation" easily with the new ZK Bind data binding system. For details about how to apply MVVM design pattern with ZK Bind, please see this series of Smalltalks[link].
+
*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].
  
=The Album Example with ZK Bind=
+
{{Template:CommentedSmalltalk_Footer|
This is an example "steal" from the article Presentation Model by Martin Fowler. The use case is simple, whenever an album is selected from the
+
|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.