ZK/操作指南/数据绑定
外观
macrobind.zul: 宏组件的“视图”定义,一个姓氏和名字填充表单。注意文本框的 onChange 事件是如何使用 ZK3 的“转发”功能传播到空间所有者的。
<?xml version="1.0" encoding="UTF-8"?> <grid> <rows> <row>First Name: <textbox id="firstName" forward="onChange=onFirstNameChange"/> </row> <row>Last Name: <textbox id="lastName" forward="onChange=onLastNameChange"/> </row> <row>Full Name: <label id="fullName"/></row> </rows> </grid>
macrobind.zs: 宏组件 Username 的类定义。它将 API 调用委派给真正的 UI 组件。
import org.zkoss.zk.ui.*; import org.zkoss.zul.*; public class Username extends HtmlMacroComponent { public void setFirstName(String str) { getFellow("firstName").setValue(str); refreshFullName(); } public String getFirstName() { return getFellow("firstName").getValue(); } public void setLastName(String str) { getFellow("lastName").setValue(str); refreshFullName(); } public String getLastName() { return getFellow("lastName").getValue(); } private void refreshFullName() { getFellow("fullName").setValue(getFirstName() + " " + getLastName()); } }
usemacrobind.zul: 使用 Username 宏组件并应用注释数据绑定的示例应用程序。注意 @{...} 绑定中的 save-when 定义。它告诉 DataBinder 在事件触发时将 Username 的值保存到 Person 对象。access:both 告诉 DataBinder Username 对象既用于加载也用于保存。底部的按钮用于检查 Person 对象的属性是否真的发生了变化。
<?xml version="1.0" encoding="UTF-8"?> <?init class="org.zkoss.zkplus.databind.AnnotateDataBinderInit" ?> <?init zscript="macrobind.zs" ?> <?component name="username" macro-uri="macrobind.zul" class="Username"?> <window xmlns:a="http://www.zkoss.org/2005/zk/annotation"> <zscript> //define a Person data object for data-binding test public class Person { private String _firstName; private String _lastName; public Person(String first, String last) { _firstName = first; _lastName = last; } public void setFirstName(String str) { _firstName = str; } public String getFirstName() { return _firstName; } public String setLastName(String str) { _lastName = str; } public String getLastName() { return _lastName; } } Person person = new Person("Hello", "World"); </zscript> <!-- see http://www.zkoss.org/javadoc/3.0.0/zkplus/org/zkoss/zkplus/databind/AnnotateDataBinder.html --> <username firstName="@{person.firstName,save-when='self.onFirstNameChange',access=both}" lastName="@{person.lastName,save-when='self.onLastNameChange',access=both}"/> <button label="check Person" onClick='alert(person.firstName+" "+person.lastName)'/> </window>
请注意,在 ZK2.4 中,无需使用“转发”功能,通过使用此版本的 macrobind.zul 可以在宏组件上显式触发事件来实现相同的功能。
<?xml version="1.0" encoding="UTF-8"?> <grid> <rows> <row>First Name: <textbox id="firstName"> <attribute name="onChange"><!-- delegate event to the Macro Component --> Events.sendEvent(spaceOwner, new Event("onFirstNameChange", spaceOwner)); </attribute> </textbox> </row> <row>Last Name: <textbox id="lastName"> <attribute name="onChange"><!-- delegate event to the Macro Component --> Events.sendEvent(spaceOwner, new Event("onLastNameChange", spaceOwner)); </attribute> </textbox> </row> <row>Full Name: <label id="fullName"/></row> </rows> </grid>
people.zs: 我们需要一些 POJO 来绑定数据。这是一个快速创建 POJO 类文件,我们将把 xul 网格绑定到这个类。
/* create a person class. chould be compiled Java on your classpath we do it in beanshell as it is quick and easy */ public class Person{ private String firstName; private String lastName; public String getFirstName(){ return firstName; } public void setFirstName(String firstName){ this.firstName = firstName; } public String getLastName(){ return lastName; } public void setLastName(String lastName){ this.lastName = lastName; } public Person(String firstName, String lastName){ this.setFirstName(firstName); this.setLastName(lastName); } }
example-people.zs: 我们需要一些示例数据 POJO。这是一个创建它们的示例文件。
// as sample list of persons. would be loaded from a database see // the sample app personA = new Person("john","wayne"); personB = new Person("jane","doe"); persons = new java.util.ArrayList(); persons.add(personA); persons.add(personB);
index.zul: 将所有内容整合到一个数据绑定示例中。
<?init zscript="people.zs" ?> <window> <zscript src="example-people.zs"/> <zscript> // down to business. define how to assign components to each // row for each object in the list that we are going to render // as rows. note the setParent(row) that hooks the new component // into the Desktop public class MyRowRenderer implements RowRenderer { public void render(Row row, Object data) { new Label("First Name:").setParent(row); new Textbox(((Person)data).getFirstName()).setParent(row); new Label("Last Name:").setParent(row); new Textbox(((Person)data).getLastName()).setParent(row); } } // create a simple data mode wapping our list of persons ListModel model = new SimpleListModel(persons.toArray()); // instantiate our custom row renderer RowRenderer rowRenderer = new MyRowRenderer(); </zscript> <!-- create a grid and assign the model and the renderer --> <grid model="${model}" rowRenderer="${rowRenderer}"/> </window>