📄 annotatedatabinder.java
字号:
/* AnnotateDataBinder.java{{IS_NOTE Purpose: Description: History: Thu Nov 16 13:22:37 2006, Created by Henri Chen}}IS_NOTECopyright (C) 2006 Potix Corporation. All Rights Reserved.{{IS_RIGHT}}IS_RIGHT*/package org.zkoss.zkplus.databind;import org.zkoss.zk.ui.Path;import org.zkoss.zk.ui.Page;import org.zkoss.zk.ui.Desktop;import org.zkoss.zk.ui.Component;import org.zkoss.zk.ui.UiException;import org.zkoss.zk.ui.sys.ComponentCtrl;import org.zkoss.zk.ui.metainfo.Annotation; import java.util.Map;import java.util.List;import java.util.ArrayList;import java.util.Map.Entry;import java.util.Iterator;/** * <p>The DataBinder that reads ZUML annotations to create binding info. The ZUML page must declare the * XML namespace, xmlns:a="http://www.zkoss.org/2005/zk/annotation", to use the ZUML annotations. * The annotation is declared before each Component or specified directly on the Component attributes. * For example, the following annotation associates the * attibute "value" of the component "textbox" to the bean's value "person.address.city".</p> * <pre> * <a:bind value="person.address.city"/> * <textbox/> * </pre> * <p>Or since ZK 2.4 you can annotate directly on the attribute "value" of the component "textbox" like this.</p> * <pre> * <textbox value="@{person.address.city}"/> * </pre> * <p>The @{...} pattern tells the ZUML parser that this is for annotation.</p> * * <p>The AnnotateDataBinder knows "a:bind" annotation only. The complete format is like this if you declared it * before the Component. * <pre> * <a:bind attrY="bean's value;[tag:expression]..."/> * <componentX/> * </pre> * * <p>You can also specify directly on the Component attribute, the complete format is like this: * <pre> * <componentX attrY="@{bean's value,[tag='expression']...}"/> * </pre> * * <p>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 a * real 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.Component#getVariable} method. That is, all those variables defined in zscript are * accessible by this DataBinder. Note that you can choose either two formats of annotaion as your will and you * can even hybrid them together though it is generaly not a good practice.</p> * * <p>The tag:expression or tag='expression' is a generic form to bind more metainfo to the attrY of the componentX. * The currently supported tag includes "load-when", "save-when", "access", and "converter"</p> * * <ul> * <li>load-when. You can specify the events concerned when to load the attribute of the component from the bean. * Multiple definition is allowed and would be called one by one. * For example, the following code snip tells DataBinder that the attribute "value" of Label "fullName" will load * from "person.fullName" when the Textbox "firstName" or "lastName" fire "onChange" event. * * <p>Declare in front of the Component:</p> * <pre> * <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"/> * </pre> * <p>Or specify directly on the Component's attribute:</p> * <pre> * <textbox id="firstname" value="@{person.firstName}"/> * <textbox id="lastname" value="@{person.lastName}"/> * <label id="fullname" value="@{person.fullName, load-when='firstname.onChange,lastname.onChange'}"/> * </pre> * </li> * * <li>save-when. You can specify the events concerned when to save the attribute of the component into the bean. * Since ZK version 3.0.0, you can specify multiple events in save-when tag (i.e. before ZK 3.0.0, you can specify only * one event). The events specified, if fired, will trigger * this DataBinder to save the attribute of the component into bean. For example, the following code snip tells * DataBinder that the attribute "value" of Textbox "firstName" will * save into "person.firstName" when the Textbox itself fire "onChange" event. * * <p>Declare in front of the Component:</p> * <pre> * <a:bind value="person.firstName; save-when:self.onChange"/> * <textbox id="firstName"/> * </pre> * * <p>Or specify directly on the Component's attribute:</p> * <pre> * <textbox id="firstName" value="@{person.firstName, save-when='self.onChange'}"/> * </pre> * * <p>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 charactieric of the component's attribute 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.</p> * <p>Declare in front of the Component:</p> * <pre> * <a:bind value="person.firstName"/> * <textbox id="firstName"/> * </pre> * <p>Or specifies directly on the Component's attribute:</p> * <pre> * <textbox id="firstName" value="@{person.firstName}"/> * </pre> * * <p>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.</p> * <pre> * <a:bind value="person.firstName; save-when:none;"/> * <textbox id="firstName"/> * </pre> * or * <pre> * <a:bind value="person.firstName; save-when: ;"/> * <textbox id="firstName"/> * </pre> * or * <pre> * <textbox id="firstName" value="@{person.firstName, save-when='none'}"/> * </pre> * or * <pre> * <textbox id="firstName" value="@{person.firstName, save-when=''}"/> * </pre> * </li> * * <p>Since 3.0.0, DataBinder supports validation phase before saving attribute content into bean property when * triggered by the specified event in save-when tag. It will fire onBindingSave event to the data-binding component and * then fire onBindingValidate to the triggering component before really saving component attribute contents into bean's * property. So application developers get the chance to handle the value validatiion 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.</p> * <pre> * <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="..."/> * </pre> * * <p>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.</p> * * <li>access. You can set the access mode of the attrY of the componentX to be "both"(load/save), * "load"(load Only), "save"(save Only), or "none"(neither). Multiple definition is NOT allowed * and the later defined would * override the previous defined one. The access mode would affects the behavior of the DataBinder's loadXxx * and saveXxx methods. * The {@link DataBinder#loadAll} and {@link DataBinder#loadComponent} would load only those attributes * with "both" or "load" access mode. The {@link DataBinder#saveAll} and * {@link DataBinder#saveComponent} would save only those attributes with "both" or "save" access mode. If you * don't specify it, the default access mode depends on the natural characteristic of the component's attribute * as defined in lang-addon.xml. For example, Label.value is default to "load" access mode while Textbox.value * is default to "both" access mode. For example, the following code snips tells DataBinder that Textbox "firstName" * would allowing doing save into bean only not the other way. * * <p>Declare in front of the Component:</p> * <pre> * <a:bind value="person.firstName;access:save;"/> * <textbox id="firstName"/> * </pre> * * <p>Or specify directly on the Component's attribute:</p> * <pre> * <textbox id="firstName" value="@{person.firstName, access='save'}"/> * </pre> * </li> * * <li>converter. You can specify the class name of the converter that implments the {@link TypeConverter} interface.
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -