We suggest annotating directly on the component property with intuitive @{...} expression because it is more readable.
For example, the following annotation associates the attribute "value" of the component "textbox" to the bean's value "person.address.city".
@{...} way:
<textbox value="@{person.address.city}"/>
The @{...} pattern tells the ZUML parser that this is for annotation.
<a:bind> way:
<a:bind value="person.address.city"/> <textbox/>
You can put more metainfo inside the @{...} or <a:bind> so this DataBinder knows what to do. The complete format is like this:
@{...} way:
<componentX attrY="@{bean's value,[tag='expression']...}"/>
<a:bind> way:
<a:bind attrY="bean's value;[tag:expression]..."/> <componentX/>
This associates the componentX's attribute attrY to the bean's value. The bean's value is something in the form of beanid.field1.field2... You can either call {@link DataBinder#bindBean} to bind the beanid to areal bean object or you can neglect it and this DataBinder would try to find it from the variables map via {@link org.zkoss.zk.ui.Page#getZScriptVariable} then {@link org.zkoss.zk.ui.Component#getVariable} method. That is, all those variables defined in zscript are also accessible by this DataBinder. Note that you can choose either two formats of annotations as your will and you can even hybrid them together though it is not generally a good practice.
The tag='expression' or tag:expression is a generic form to bind more metainfo to the attrY of the componentX. The currently supported tags includes "load-when", "save-when", "access", "converter", "load-after"(since 3.6.1), and "save-after"(since 3.6.1).
The @{...} way that specify directly on the Component's attribute:
<textbox id="firstname" value="@{person.firstName}"/> <textbox id="lastname" value="@{person.lastName}"/> <label id="fullname" value="@{person.fullName, load-when='firstname.onChange,lastname.onChange'}"/>
Or the <a:bind> way that declare in front of the Component:
<a:bind value="person.firstName"/> <textbox id="firstname"/> <a:bind value="person.lastName"/> <textbox id="lastname"/> <a:bind value="person.fullName; load-when:firstname.onChange; load-when:lastname.onChange"/> <label id="fullname"/>
The @{...} way that specify directly on the Component's attribute:
<textbox id="firstName" value="@{person.firstName, save-when='self.onChange'}"/>
Or the <a:bind> way that declare in front of the Component:
<a:bind value="person.firstName; save-when:self.onChange"/> <textbox id="firstName"/>
However, you don't generally specify the save-when tag. If you don't specify it, the default events are used depends on the natural characteristic of the component's property as defined in lang-addon.xml. For example, the save-when of Label.value is default to "none" while that of Textbox.value is default to "self.onChange". That is, the following example is the same as the above one.
The @{...} way that specify directly on the Component's attribute:
<textbox id="firstName" value="@{person.firstName}"/>
Or the <a:bind> way that declare in front of the Component:
<a:bind value="person.firstName"/> <textbox id="firstName"/>
On the other hand, you might not specify the save-when tag nor you want the default events to be used. Then you can specify a "none" keyword or simply leave empty to indicate such cases.
<textbox id="firstName" value="@{person.firstName, save-when='none'}"/>or
<textbox id="firstName" value="@{person.firstName, save-when=''}"/>or
<a:bind value="person.firstName; save-when:none;"/> <textbox id="firstName"/>or
<a:bind value="person.firstName; save-when: ;"/> <textbox id="firstName"/>
The @{...} way that specify directly on the Component's attribute:
<textbox id="firstName" value="@{person.firstName, access='save'}"/>
Or the <a:bind> way that declare in front of the Component:
<a:bind value="person.firstName;access:save;"/> <textbox id="firstName"/>
(Since 3.1) If you specify some tags other than the supported tags, they will be put into an argument Map and is stored as a component's custom attribute (componentScope) with key name "bindingArgs" (no matter annotated in which attribute of the component). e.g. Then mylabel.getAttribute("bindingArgs") will return a Map with {answer=yes, question=no} two entries (Since 3.1) We support the "distinct" concept for collection components with "model" attribute(i.e. Grid, Listbox, Comobobox, etc.). You can specify as follows to tell the Data Binder that there might be one same object in multiple entries. or The default value for distinct is "true". However, if you specify distinct=false, the DataBinder will scan the whole ListModel to find out all items with the specified objects (thus worse performance if a big ListModel). (Since 3.6.2) if you specify some tags other than the supported tags, they will be put into an argument Map and is stored as a component's custom attribute(componentScope) with key name "Xxx_bindingArgs" where the Xxx is the name of the annotated component attribute. e.g. Then mylabel.getAttribute("value_bindingArgs") will return a Map with {answer=yes} entry and mylabel.getAttribute("style_bindingArgs") will return another Map with {question=no} entry. Since 3.0.0, DataBinder supports validation phase before doing a save. Note that a DataBinder "save" is triggered by a component event as specified on the "save-when" or "save-after" tag. Before doing a save, it first fires an onBindingSave event to each data-binding component and then it fires an onBindingValidate event to the event triggering component before really saving component property contents into bean's property. So application developers get the chance to handle the value validation before saving. In the following example when end user click the "savebtn" button, an "onBindingSave" is first fired to "firtName" and "lastName" textboxes and then an "onBindingValidate" is fired to "savebtn" button. Application developers can register proper event handlers to do what they want to do. Note that the original textbox constraint mechanism is still there. This DataBinder validation phase is an add-on feature that can be applied to all components and attributes that use data binding mechanism. <label id="mylabel" value="@{person.name, answer='yes'}" style="@{person.mystyle, question='no'}">
<grid model="@{persons, distinct=false}" ...> ... </grid>
<a:bind model="persons; distinct:false"/> <grid ...> ... </grid>
<label id="mylabel" value="@{person.name, answer='yes'}" style="@{person.mystyle, question='no'}">
<textbox id="firstName" value="@{person.firstName, save-when="savebtn.onClick"}" onBindingSave="..."/> <textbox id="lastName" value="@{person.lastName, save-when="savebtn.onClick"}" onBindingSave="..."/> <button id="savebtn" label="save" onBindingValidate="..."/>
|
|
|
|
|
|