ZK/操作指南/组件开发
首先设置包含要扩展的网格的页面
<?page id="main-page"?> <window title="Expanding Grid" border="normal" width="360px" id="food-to-go-delegate"> <zscript> String[][] values = { {"one", "1"} ,{"two","2"} }; </zscript> <grid> <columns> <column label="Menu Item" sortAscending="${asc}" sortDescending="${dsc}"/> <column label="Price"/> </columns> <rows id="rows" use="org.zkforge.ftg.ExpandingMenuItemRows"> <row forEach="${values}"> <label value="${each[0]}"/> <hbox>$<textbox value="${each[1]}"/></hbox> </row> </rows> </grid> <button label="Add More"> <attribute name="onClick"><![CDATA[ Window win = (Window) Executions.createComponents( "menu-items-popup.zul", null, null); win.doModal(); ]]></attribute> </button> </window>
这里有很多内容。首先,有一个名为“values”的静态数组。这只是一个简单的演示,我们可以使用 forEach="${values}" 来输出行列表。实际上,这些数据应该从数据库中获取。接下来要注意的是,id 为“rows”的 <rows> 标签有一个“use”属性,它指定使用 org.zkoss.zul.Rows 的子类来实现该 xul 元素。在这个自定义子类中,我们可以添加一个自定义方法来将新行插入网格中
package org.zkforge.ftg; import org.zkoss.zul.Hbox; import org.zkoss.zul.Label; import org.zkoss.zul.Row; import org.zkoss.zul.Rows; import org.zkoss.zul.Textbox; public class ExpandingMenuItemRows extends Rows { /* * This is just an arbitrary custom method that we can call from a zscript. * In it we programmatically create all of the elements that appear in the other * rows. The code below simply creates: * <row><label value=""/><hbox>$<textbox value=""/></hbox></row> * and sets the two value attributes whatever was passed into the method. */ public void addRow(String name, String price){ Label label = new Label(); label.setValue(name); Label dollar = new Label(); dollar.setValue("$"); Textbox textbox = new Textbox(); textbox.setValue(price); Hbox hbox = new Hbox(); hbox.appendChild(dollar); hbox.appendChild(textbox); Row row = new Row(); row.appendChild(label); row.appendChild(hbox); this.appendChild(row); } }
因此,如果我们可以获得一个 zscript 函数来调用该方法,那么新的行将被追加到网格中。这种逻辑位于弹出窗口中的 menu-items-popup.zul 文件中
<window id="win" title="Add Menu Item" border="normal" width="200px" closable="true"> <zscript> doAdd(String name, String price){ rows = Path.getComponent("//main-page/food-to-go-delegate/rows"); rows.addRow(name, price); } </zscript> <vbox>Name:<textbox id="name" value=""/> Price:<textbox id="price" value=""/></vbox> <button label="Add" onClick="doAdd(name.value,price.value);win.detach()"/> <button label="Cancel" onClick="win.detach()"/> </window>
在这个模式对话框中,我们有两个文本框,一个用于名称,一个用于价格。如果用户点击“添加”,按钮将调用一个 zscript 函数 doAdd,并将这两个文本框的值传递给它。doAdd() 然后对主页面中的 <rows> 元素执行 IDSpace 查找。<rows> 在页面 “main-page” 上,id 为 “food-to-go-delegate” 的窗口的 IDSpace 中有一个 id 为“rows”。我们可以使用语法“//page/window/id” 来写出来。一旦我们获得了自定义子类元素的引用,我们就可以调用我们的自定义方法“addRow”。
如果你想开发一个可以通过 zk.xml 配置的组件,那么你需要
1) 定义一个部署者可以在 WEB-INF/zk.xml 中使用的偏好名称。例如,
<!-- zk.xml --> <preference> <name>org.zkoss.zul.Window.defaultActionOnShow</name> <value>moveDown</value> </preference>
2) 使用 org.zkoss.zk.ui.util.Configuration 类的 getPreference 方法访问它。
然而,每个 Web 应用程序只有一个 Configuration 实例,如果多个 Web 应用程序共享 ZK 库(例如,zk.jar),那么组件可能属于任何 Web 应用程序。因此,只有在组件附加到页面时才能访问偏好设置。一个好的时机是在组件被渲染时。例如,
//Window.java //getOuterAttrs is called when redraw() is called public String getOuterAttrs() { StringBuffer sb = new StringBuffer().append(super.getOuterAttrs()); HTMLs.appendAttribute(sb, "z.aos", getDesktop().getWebApp().getConfiguration() .getPreference("org.zkoss.zul.Window.defaultActionOnShow")); return sb.toString(); }
如果你想提供一个静态方法来设置默认值(覆盖偏好设置)
public String getOuterAttrs() { StringBuffer sb = new StringBuffer().append(super.getOuterAttrs()); String aos = getDefaultActionOnShow(); if (aos == null) aos = getDesktop().getWebApp().getConfiguration() .getPreference("org.zkoss.zul.Window.defaultActionOnShow"); HTMLs.appendAttribute(sb, "z.aos", aos); return sb.toString(); } public static String getDefaultActionOnShow() { return _daos; }