<forEach>
跟 Listbox, Grid 同样支援 model-driven rendering,也就是基於 ListModel
来绘制画面,你只要变更 ListModel
物件内容,ZK 会自动帮你更新到浏览器页面。例如下面是一个新增、删除、排序名字列表的应用:
<groupbox width="450px" apply="quickstart.shadow.ForEachComposer" mold="3d">
<div>
<forEach id="namesList" var="name">
<span sclass="nameTag">
<label value="${name}"/>
</span>
</forEach>
</div>
</groupbox>
<forEach>
id 好让我可以在控制器中取得参照。var
属性是把预设的隐含变数名称 each
改名为 name
,这样在 <forEach>
内部就必须要用 ${name}
来存取集合物件内每个物件,这是一个增加可读性的功能,不改也不影响功能。public class ForEachComposer extends SelectorComposer<Component> {
@Wire("::shadow#namesList")
private ForEach namesList;
private ListModelList<String> namesModel;
@Override
public void doAfterCompose(Component comp) throws Exception {
super.doAfterCompose(comp);
namesModel = new ListModelList<String>(new String[] {"Chris", "Elisabeth", "Aaron", "Berta", "Daniel"});
namesList.setItems(namesModel);
namesList.recreate();
setItems()
把初始化好的资料模型 ListModelList
赋予给 nameList
,再呼叫 recreate()
重建 <forEach>
的元件
增加一个 <textbox>
并把事件转发到根元件上。
<groupbox width="450px" apply="quickstart.shadow.ForEachComposer" mold="3d">
<div>
<forEach id="namesList" var="name">
<span sclass="nameTag">
<label value="${name}"/>
</span>
</forEach>
</div>
<textbox forward="onOK=onAddName" placeholder="New Name + ENTER"/>
</groupbox>
onOK
事件发生在使用者在 <textbox>
内按下 Enter 键,这样好处是可以免去点击「增加」按钮的操作<groupbox>
@Override
public void doAfterCompose(Component comp) throws Exception {
super.doAfterCompose(comp);
...
comp.addEventListener("onAddName", (EventListener<ForwardEvent>)this::addName);
}
private void addName(ForwardEvent event) {
Textbox nameInput = (Textbox) event.getOrigin().getTarget();
Optional.ofNullable(nameInput.getValue())
.filter(v -> !namesModel.contains(v)) //ignore duplicates
.ifPresent(namesModel::add);
nameInput.setValue("");
}
addEventListener()
namesModel::add
,zk 就会帮你通知 <forEach>
并更新页面
在名字後面增加一个 X 图示来作为「移除」按钮
<forEach id="namesList" var="name">
<span sclass="nameTag" >
<label value="${name}"/>
<a forward="onClick=onRemoveName(${name})" iconSclass="z-icon-times"/>
</span>
</forEach>
<groupbox>
,这样的好处是,我可以统一把倾听器都注册在 <groupbox>
,比较好维护。如果注册在内部子元件 <a>
上,如果未来要换成别的元件,就要修改程序onRemoveName(${name})
:这写法就能把名字当作参数传进倾听器中public void doAfterCompose(Component comp) throws Exception {
super.doAfterCompose(comp);
...
comp.addEventListener("onRemoveName", event -> namesModel.remove((String) event.getData()));
}
event.getData()
取得先前传入的参数(名字)
加2个排序按钮,分别是升序与降序排序:
<button forward="onSortAsc" iconSclass="z-icon-sort-alpha-asc"/>
<button forward="onSortDesc" iconSclass="z-icon-sort-alpha-desc"/>
呼叫 ListModelList.sort()
来排序即可
@Override
public void doAfterCompose(Component comp) throws Exception {
super.doAfterCompose(comp);
...
comp.addEventListener("onSortAsc", event -> namesModel.sort(String.CASE_INSENSITIVE_ORDER));
comp.addEventListener("onSortDesc", event -> namesModel.sort(String.CASE_INSENSITIVE_ORDER.reversed()));
...
}
增加一个清除全部按钮
<button forward="onClearAll" iconSclass="z-icon-user-times" tooltiptext="clear all"/>
呼叫 ListModelList.clear()
@Override
public void doAfterCompose(Component comp) throws Exception {
super.doAfterCompose(comp);
...
comp.addEventListener("onClearAll", event -> namesModel.clear());
...
}
透过以上例子应该可以看出,用 <forEach>
再搭配 ListModelList
即可以快速做出新增、删除等各种操作集合物件的功能。
>>: IOS、Python自学心得30天 Day-29 连接Firebase辨识
上一篇我们完成了wireframe的绘制,这次我们要将草稿跟库拉皮卡一样,没有办法下船更具现化一点,...
前面讲了那麽多,当然在部属unRaid还是要优先考虑设备的选择 当然用淘汰的旧电脑也是可以(小雨这次...
来源 : emcthye - FxRate 架构图 MVP Base CurrencyListAct...
打了这麽多的技术文,突然发现我好像都没有介绍到资安的基础,所以最後的这 3 篇文章可能就是做个资安的...
Virtual Judge ZeroJudge 题意 \TeX/ \LaTeX/ 输入一字串,重新...