on June 30, 2010, I have met a question In ZK client programming, 使用 ZK的方便之处就是基于注 解"@{}",但所有的事物都是双刃剑,当我们使用注解实现AfterCompse接口 zk自动帮我们绑定后台的对象,但当我们对同一对象重用时,我们必须还需在后台把它的实例给销毁,然后重新绑定对象.这样的一来一回会减低我们的开发效率.
所以使用ZK注解开发人员应该考虑相应系统的复杂性和重用性后酌情处理。
下面的例子是在开发中动态生成Component组件 并使用客户端技术JQuery 实现功能
1.后台Java类中动态生成Grid 容器组件的子组件 把在这些组件创建时绑定数据然后再返回给zul页面显示数据.
Java代码
package com.linktel.linkFax.web.zk.controller;
import java.awt.Checkbox;
import java.util.Iterator;
import java.util.List;
import org.apache.commons.lang.StringUtils;
import org.zkoss.zk.ui.Components;
import org.zkoss.zk.ui.event.Event;
import org.zkoss.zk.ui.event.EventListener;
import org.zkoss.zk.ui.ext.AfterCompose;
import org.zkoss.zkplus.databind.AnnotateDataBinder;
import org.zkoss.zkplus.spring.SpringUtil;
import org.zkoss.zul.Window;
import org.zkoss.zul.api.Combobox;
import org.zkoss.zul.api.Div;
import org.zkoss.zul.api.Grid;
import org.zkoss.zul.api.Label;
import org.zkoss.zul.api.Row;
import org.zkoss.zul.api.Rows;
import com.linktel.linkFax.domain.Authority;
import com.linktel.linkFax.domain.Role;
import com.linktel.linkFax.service.AuthorityService;
import com.linktel.linkFax.service.RoleService;
import com.linktel.linkFax.web.zk.util.ZkUtils;
public class AuthorityController extends Window implements AfterCompose {
private static final long serialVersionUID = 1L;
private Role role = new Role();
private Authority authority=new Authority();
private List<Authority> authorities;
private List<Role> roles;
protected Grid gdAuthorities;
protected AnnotateDataBinder binder;
private Combobox cbxRole;
public Role getRole() {
return role;
}
public void setRole(Role role) {
this.role = role;
}
public Authority getAuthority() {
return authority;
}
public void setAuthority(Authority authority) {
this.authority = authority;
}
public List<Authority> getAuthorities() {
return authorities;
}
public void setAuthorities(List<Authority> authorities) {
this.authorities = authorities;
}
public List<Role> getRoles() {
return roles;
}
public void setRoles(List<Role> roles) {
this.roles = roles;
}
@Override
public void afterCompose() {
Components.wireVariables(this, this);
Components.addForwards(this, this);
init();
}
public void onCreate() {
binder = (AnnotateDataBinder) this.getAttribute("binder", true);
}
/*
* 页面加载实现afterComposer()方法初始化
* 动态创建Grid组件Rows中的Checkbox 组件并绑定数据
*/
@SuppressWarnings("unchecked")
public void init() {
RoleService roleService = (RoleService) SpringUtil
.getBean("roleService");
roles = roleService.getRolesAll();
AuthorityService authService = (AuthorityService) SpringUtil
.getBean("authorityService");
authorities = authService.getAuthoritiesAll();
Rows rows=gdAuthorities.getRowsApi();
List<Row> rowList=rows.getChildren();
for(int i=0;i<authorities.size();i++){
Authority authority= authorities.get(i);
Row row=new org.zkoss.zul.Row();
Div div=new org.zkoss.zul.Div();
org.zkoss.zul.api.Checkbox chk=new org.zkoss.zul.Checkbox();
Label lblId=new org.zkoss.zul.Label();
lblId.setValue(authority.getId().toString());
Label lblDisName=new org.zkoss.zul.Label();
lblDisName.setValue(authority.getDisplayName());
chk.setParent(div);
lblId.setParent(div);
div.setParent(row);
lblDisName.setParent(row);
rowList.add(row);
}
}
以上我们实现了,动态生成组件绑定数据,下面我们来实现Zul页面(全选)Checkbox 对动态生成组件的(全选/选不选)
Xml代码
<?xml version="1.0" encoding="utf-8"?> <?page id="authorityPage"?> <?xel-method prefix="c" name="hasPermission" class="com.linktel.linkFax.web.zk.util.AuthorityTools" signature="com.linktel.linkFax.web.zk.util.AuthorityTools hasPermission(java.lang.String)"?> <?init class="org.zkoss.zkplus.databind.AnnotateDataBinderInit" root="./authorityWin"?> <window id="authorityWin" use="com.linktel.linkFax.web.zk.controller.AuthorityController" width="100%" xmlns:h="http://www.w3.org/1999/xhtml" xmlns:n="http://www.zkoss.org/2005/zk/native" xmlns="http://www.zkoss.org/2005/zul" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.zkoss.org/2005/zul http://www.zkoss.org/2005/zul/zul.xsd" xmlns:w="http://www.zkoss.org/2005/zk/client"> <grid id="gdAuthorities" mold="paging" paginal="@{pagingId}" fixedLayout="true"> <columns> <column> <checkbox w:onCheck=" var allCtrl = this; jq('@checkbox',this.parent.parent.nextSibling).each( function(i,chk){ var c =zk.Widget.$(chk); if(allCtrl.isChecked()){ c.setChecked(true); }else{ c.setChecked(false); } });"></checkbox> </column> <column></column> </columns> <rows> </rows> </grid> </window>
首先我们客户端编程需要引入命名空间 xmlns:w=http://www.zkoss.org/2005/zk/client
ZK引擎是基于Jquery实现的, 我们使用zk给我们提供的JQuery类库 ZK中w:onCheck="" 在用户选中一个复选按钮时触发一个oncheck客户端事件,jq(@window,this.parent.nextSibling).each(...);@window是checkbox组件类型,this.parent.nextSibling是找到当前组件的父组件的同级组件;each(.....)对嵌套的组件进行遍历,each(....)中定义匿名函数,function(i,chk){...} chk参数就是被迭代的子组件,zk5.0.2中checkbox其实不具有客户端checkbox的任何行(action)为,所以我们必须用zk.Widget.$(chk);转换成Widget客户端的组件这样它才真正具有了checkbox的行为(action).转换成widget的组件后我们就可以在客户端对checkbox进行
(全选/全部选).
以上的功能实现是在和同事(张学化)的讨论下完成的。