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进行
(全选/全部选).
以上的功能实现是在和同事(张学化)的讨论下完成的。