Envisage ZK 6: The Next Generation Data Binding System

From Documentation
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.