跳轉至內容

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>

如何從 Java 物件集合動態呈現網格?

[編輯 | 編輯原始碼]

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>
華夏公益教科書