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>