To enable the data binding in the ZUL, you have to apply a BindComposer on a component (said Root component of this data binding). The BindComposer implements Composer and plays a role to activate data binding mechanism for a component and its children components. It also initializes a Binder and ViewModel and passes ViewModel object's reference to Binder.

Apply BindComposer

To use a ViewModel you have to apply a BindComposer by setting “org.zkoss.bind.BindComposer” to “apply” attribute of a component.

<window id="win" apply="org.zkoss.bind.BindComposer">
<!-- other components inside will have data binding ability-->

Since 8.0.0

In ZK 8, BindComposer is auto-applied when the attribute of viewModel is being used. Notice that if you want to use another Composer, you will need to apply the BindComposer yourself.

Initialize a ViewModel

You also have to specify ViewModel's full-qualified class name to initialize it and give it an ID. The typical usage is like:

<window id="win" apply="org.zkoss.bind.BindComposer"
        viewModel="@id('vm') @init('foo.MyViewModel')">
    <label value="@load(vm.message)"/>
<!-- other components -->

In above code example, after the target component, window, is composed, the BindComposer will try to resolve the string literal inside @init() as a Class object and instantiate it. If it succeeds, it will store ViewModel object as an attribute of the root component for future use and it stores with the key vm which is specified in @id. Therefore, any child component of <window> can reference ViewModel by the id vm.

If there is no ViewModel attribute specified, the binder itself will become the ViewModel. That means you can apply a ViewModel which inherit BindComposer without specifying ViewModel attribute, but we only suggest this usage for experienced ZK user.

Wire Variable Automatically

If a member field is annotated by @WireVariable in a ViewModel, the variable (if existed) will be wired into this field automatically before connecting Binder and ViewModel. Read Wire Variable for more detail about wiring variables. Following is a example that shows how to wire a messagService variable to the ViewModel.

public class OrderVM {

    MessageService messageService;

    //rest of the class...

Initialize Binder

If you don't specify a root component's binder attribute, BindComposer creates AnnotateBinder by default. You usually don't have to specify binder attribute unless you want to use your own binder. You can get the Binder object by invoking getAttribute("binder") on the root component. In above example, it's win.getAttribute("binder"). We only suggest this usage to experienced ZK users.

Initialize Validation Message Holder

The validate message holder is also created by BindComposer. It's a container of validation messages that are generated by Validator during validation. Before using validation message holder, we have to give it an id in validationMessages attribute. We can retrieve validation message from it with a component as a key. We'll describe the detail in section

<window title="Order Management" border="normal" width="600px"
    apply="org.zkoss.bind.BindComposer" viewModel="@id('vm') @init(orderVm)"
            <intbox id="qbox" value="@load(vm.selected.quantity)
                @save(vm.selected.quantity, before='saveOrder')
            <label value="@bind(vmsgs[qbox])" sclass="red" />
  • Give validation message holder an id in order to reference it. (line 3)
  • We can retrieve validation messages of a input component, it's qbox, with the component as a key. (line 8)