跳转至内容

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>
华夏公益教科书