Skip to content

Commit

Permalink
v0.5 document update
Browse files Browse the repository at this point in the history
  • Loading branch information
xiaochong committed Feb 18, 2012
1 parent 25a53e8 commit a868607
Show file tree
Hide file tree
Showing 3 changed files with 123 additions and 295 deletions.
179 changes: 1 addition & 178 deletions src/docs/guide/3.9 The Next Generation Data Binding System.gdoc
@@ -1,184 +1,7 @@
h3. Introduction
ZK Bind is a whole new data binding system with new specifications and implementations.

h3. Features

h4. A whole new, clean annotation expression
* Same Java style annotation expression: 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.
** @bind(...): used to bind data and command along with parameters
** @converter(...): used to specify converters along with parameters
** @valiator(...): used to specify validators along with parameters
** @form(...): used to bind a form.

h4. EL 2.2 flexiable expressions
* ZK Bind accept EL 2.2 syntax expression that 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.
{code:xml}
<z:image src="@bind(vm.person.boy ? 'boy.png' : 'girl.png')"/>

<z:button onClick="@bind(vm.add ? 'add' : 'update')" label="@bind(vm.add ? 'Add' : 'Update'"/>

<z:button onClick="@bind('subscribe')" disabled="@bind(empty vm.symbol)" label="Subscribe"/>
{code}

h4. 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

{code:xml}
<z:label value="@bind(load=vm.person.fullname)"/>

<z:label value="@bind(load=vm.person.firstname after 'update')"/>

<z:label value="@bind(load=vm.person.firstname before 'delete')"/>

<z:label value="@bind(load={vm.person.firstname after 'update', vm.person.message after 'delete'})"/>
{code}

h4. 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

{code:xml}
<z:textbox value="@bind(save=vm.person.firstname)"/>

<z:textbox value="@bind(save={vm.person.firstname, vm.tmpperson.firstname})"/>

<z:textbox value="@bind(save=vm.person.firstname before 'update')"/>

<z:textbox value="@bind(save=vm.person.firstname after 'delete'"/>

<z:textbox value="@bind(save={vm.selected.firstname before 'update', vm.newperson.firstname before 'add'}"/>
{code}

h4. Initial data binding
* Load when UI components are first added into the binding system
{code:xml}
<z:label value="@bind(init=vm.selected.firstname)"/>
{code}

h4. 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
{code:xml}
<z:textbox value="@bind(vm.person.firstname)"/>

<z:textbox value="@bind(load=vm.selected.firstname, save={vm.selected.firstname, vm.newperson.firstname before 'add'})"/>
{code}

h4. Bind to any attributes of the UI components
* Bind symmetrically to all attributes of UI components
{code:xml}
<z:textbox value="@bind(vm.symbol)" instant="true"/>
<z:button onClick="@bind('subscribe')" disabled="@bind(empty vm.symbol)" label="Subscribe" />
{code}

h4. Event command binding
* Bridge ZK event to command
* Automatic event listener registration
* Simple command name invocation
{code:xml}
<z:button onClick="@bind('subscribe')" disabled="@bind(empty vm.symbol)" label="Subscribe" />
{code}

h4. Template/Collection binding
* Binding on Listbox/Grid/Tree/Combobox
* Local variable scope is limited to the container component
* Support index property
{code:xml}
<z:listbox width="300px" model="@bind(vm.albumList)" selectedItem="@bind(vm.selectedAlbum)" vflex="true">
<z:template name="model" var="a">
<listitem label="@bind(a.title)"/>
</z:template>
</z:listbox>
{code}

h4. Form binding
* Middle form binding to avoid affecting back-end data beans
* Submit a form in a whole
* Conditional save for different commands
{code:xml}
<z:grid self="@form(id='fx', load=vm.selected, save={vm.selected before 'update', vm.newAlbum before 'add'})">
<z:row>Title: <z:textbox value="@bind(fx.title)"/></z:row>
<z:row>Artist: <z:textbox value="@bind(fx.artist)"/></z:row>
<z:row><z:checkbox checked="@bind(fx.classical)"/> Classical</z:row>
<z:row>Composer: <z:textbox value="@bind(fx.composer)"/></z:row>
</z:grid>
<z:button onClick="@bind('add')" label="Add"/>
<z:button onClick="@bind('update')" label="Update"/>
{code}

h4. Java annotated data dependency tracking
* Controllable load on save
* @NotifyChange to notify property changes
* @DependsOn to specify property change dependency
{code}
@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;
}
{code}

h4. Embedded validation cycle
* 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
* Validate a single property or a form
* Validate on a command
{code:xml}
<z:textbox value="@bind(save=vm.selected.firstname) @validator('noEmpty')"/>
<z:grid self="@form(id='fx', load=vm.selected, save=vm.selected before 'update') @validator(vm.passwordValidator)">
<z:row>username<textbox value="@bind(fx.username)"/></z:row>
<z:row>password<textbox value="@bind(fx.password)" type="password"/></z:row>
<z:row>retype password<textbox value="@bind(fx.retypePassword)" type="password"/></z:row>
</z:grid>
{code}

h4. Enhanced converter mechanism
* 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
{code:xml}
<z:datebox value="@bind(vm.selected.birthday) @converter('formatedDate', format='yyyy/MM/dd')"/>
{code}

h4. org.zkoss.bind.BindComposer
* Ease UI components, binder, and ViewModel association
* Each binder covers only the applied component tree
* Inter-binder communications
{code:xml}
<z:window apply="org.zkoss.bind.BindComposer" viewModel="@bind(vm='org.zkoss.mvvm.examples.album.AlbumViewModel')">
...
</z:window>
{code}

h4. Bind on demand
* Support dynamically 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.

h4. 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 in parallel independently.
** Can add new Views or change current View easily.
** Different views for different devices with a common ViewModel.
** Allow unit-test ViewModel independently without UI environments.

h4. For details
For details

[Envisage ZK 6: The Next Generation Data Binding System|http://books.zkoss.org/wiki/Small_Talks/2011/October/Envisage_ZK_6:_The_Next_Generation_Data_Binding_System]

Expand Down
33 changes: 18 additions & 15 deletions src/docs/guide/9.1 Hello MVVM.gdoc
Expand Up @@ -53,34 +53,36 @@ Apparently, UI designer has to tell binder at least the following things:
In ZK Bind, ZK Annotation is utilized to do these jobs:
@View@: helloMVVM.gsp
{code:xml}
<z:window apply="org.zkoss.bind.BindComposer" viewModel="@bind(vm='org.zkoss.mvvm.examples.hello.HelloViewModel')">
<z:label value="@bind(vm.message)"/>
<z:button label="Show" onClick="@bind('showHello')"/>
<z:window apply="org.zkoss.bind.BindComposer" viewModel="\@id('vm')\@init('demo.HelloVM')">
<z:label value="\@bind(vm.message)"/>
<z:button label="Show" onClick="\@command('showHello')"/>
</z:window>
{code}

@ViewModel@: HelloViewModel.groovy
@ViewModel@: HelloVM.groovy
{code}
class HelloViewModel {
class HelloVM {
private String message

public String getMessage() {
return message
}

@NotifyChange("message")
\@Command \@NotifyChange("message")
public void showHello() {
message = "Hello World!"
}

}
{code}

Per this example, let's run through the program flow:
# When end user press the "Show" button, the onClick event is fired to binder.
# The binder finds that the command name in the ViewModel which is "showHello" as specified in the ZK annotation @bind('showHello').
# The binder calls the showHello() method in the HelloViewModel and changes the message property. Note that the @NotifyChange("message") Java method annotation on showHello() method in HelloViewModel. It tells the binder that the property message in the HelloViewModel will be changed if this command is called.
# The binder then finds that the attribute value of component label is associated with the changed message property of the HelloViewModel(as specified in ZK annotation @bind(vm.message)). So it loads data from the property vm.message and updates the label's value attribute. The new message "Hello World!" is then shown on the screen and provides the visual feedback to the end user.
# The binder finds that the command name in the ViewModel which is "showHello" as specified in the ZK annotation @command('showHello').
# The binder calls the showHello() method in the HelloVM and changes the message property. Note that the @NotifyChange("message") Java method annotation on showHello() method in HelloVM. It tells the binder that the property message in the HelloVM will be changed if this command is called.
# The binder then finds that the attribute value of component label is associated with the changed message property of the HelloVM(as specified in ZK annotation @bind(vm.message)). So it loads data from the property vm.message and updates the label's value attribute. The new message "Hello World!" is then shown on the screen and provides the visual feedback to the end user.

In this MVVM implementation with data binding system, the HelloViewModel is a simple POJO and refers none of the UI components. It only exposes the message contents via getMessage() and provides the necessary action logic showHello(). It does not know how these information or action logic will be used. It is the UI designer's job to decide which UI components are to be used in which layout as seen in HelloMVVM.gsp.
In this MVVM implementation with data binding system, the HelloVM is a simple POJO and refers none of the UI components. It only exposes the message contents via getMessage() and provides the necessary action logic showHello(). It does not know how these information or action logic will be used. It is the UI designer's job to decide which UI components are to be used in which layout as seen in HelloMVVM.gsp.

h3. The example revised -- Pop Up the Message

Expand Down Expand Up @@ -124,18 +126,19 @@ h3. Revised MVVM Implementation

View: helloMVVM2.gsp
{code:xml}
<z:window apply="org.zkoss.bind.BindComposer" viewModel="@bind(vm='org.zkoss.mvvm.examples.hello.HelloViewModel')">
<z:button label="Show" onClick="@bind('showHello')"/>
<z:window apply="org.zkoss.bind.BindComposer"
viewModel="\@id('vm')\@init('demo.HelloVM')">
<z:button label="Show" onClick="\@command('showHello')"/>
<z:window title="Hello" width="300px" height="200px" mode="modal"
visible="@bind(not empty vm.message)">
visible="\@bind(not empty vm.message)">
<z:hbox align="center" pack="center" hflex="true" vflex="true">
<z:label value="@bind(vm.message)"/>
<z:label value="\@bind(vm.message)"/>
</z:hbox>
</z:window>
</z:window>
{code}

The advantages of using MVVM design pattern comes in when customers changes their requirements on the View. UI Designers can proceed the changes independently and the HelloViewModel java file does not have to be changed because what the customer required was to change the way how the message is presented not the message itself. Notice that here the show/hide of the modal window is controlled whether the message is empty or not(visible="@bind(not empty vm.message)").
The advantages of using MVVM design pattern comes in when customers changes their requirements on the View. UI Designers can proceed the changes independently and the HelloVM java file does not have to be changed because what the customer required was to change the way how the message is presented not the message itself. Notice that here the show/hide of the modal window is controlled whether the message is empty or not(visible="@bind(not empty vm.message)").


h3. See more
Expand Down

0 comments on commit a868607

Please sign in to comment.