在伺服器的控制器(ZK composer)載入資料後,要讓它跟 zul 上寫的元件關聯,才能實際控制 zul上的元件,於是我在最上層的元件 <div>上的 apply 寫上完整 class 名稱:
<div width="20%" apply="quickstart.hero.HeroController" style="margin: 0 auto">
<h:h3>復仇者英雄列表</h:h3>
<listbox id="heroBox" rows="5" emptyMessage="無資料">
...
</listbox>
當我想控制 <div> 跟其下子元件時,我就必須將控制器關聯到該元件。
控制器的生命週期是由 ZK 決定,因此你無需寫程式去產生該物件。當一個瀏覽器訪問這個 zul 時,ZK 就會新建一個控制器物件,並呼叫對應的生命週期方法,如 doAfterCompose(),也會剖析 zul 檔將對應的元件生成,並綁定到我所指定的控制器上去。
要用 Listbox 顯示資料前先了解 ZK 針對資料元件(例如Listbox, Grid, Tree)及一些支援 model 屬性的元件(如 Tabbox, Selectbox, Searchbox等)的設計架構都是採用「資料模型驅動繪製」。元件(Listbox)、zul、資料模型(ListModel),3者之間形成 MVC pattern。
以 Listbox 為例,開發者把資料模型 (ListModelList) 塞給元件 (Listbox),元件根據模板或繪製器 (<template>, ListItemRender) 生成其對應的子元件 (Listitem)。開發者需透過操控資料模型(ListModel)的內容來控制子元件而不是直接生成/消滅子元件。

add(), remove(), clear() 被呼叫時setModel() 只是將資料塞給 Listbox,預設 Listbox 會呼叫 toString() 把每個 Hero 繪製出來,但這通常不是我們想要的。因此我要定義一個範本來決定怎麼繪製每一個 Hero 物件,語法如下:
<listbox id="heroBox" rows="5" emptyMessage="無資料" >
<listhead>
<listheader width="50px"/>
<listheader />
</listhead>
<template name="model">
<listitem>
<listcell label="${forEachStatus.index}"/>
<listcell label="${each.name}"/>
</listitem>
</template>
</listbox>
<listheader> 控制欄位寬度<template> 用來定義範本,name 的值必須是 model,代表是給 model 用的範本。${each} 是 ZK 預設定義的隱含變數,代表 model 中的每個物件,在我們的例子中是 Hero,用 dot notation 來存取 Java bean 物件上的屬性如 ${each.name}
${forEachStatus.index} 也是隱含變數,用來存取model索引值,從0 開始