Suggested case list:
Using timer to refresh a grid
383guest172.69.33.12125nk0uiMay 7, 2020 7:23:47 AMlinkuser model to move item to another listbox
120guest162.158.193.148d0n3krApr 2, 2020 5:28:28 AMlinkDisabled list item row passed to VM-1981
296fatih123160.83.36.13025nk0uiFeb 13, 2018 4:25:44 PMlinkDisabled list item row passed to VM-1981
295fatih123160.83.36.13025nk0uiFeb 13, 2018 4:25:16 PMlinkDisabled list item row passed to VM-1981
294fatih123160.83.36.13225nk0uiFeb 13, 2018 3:30:44 PMlinkgrid sample with ListModel/RowRenderer
816guest80.82.2.1312vah9ajFeb 21, 2017 11:42:21 AMlinkgrid sample with ListModel/RowRenderer
809guest175.98.113.1622vah9ajJan 26, 2017 9:19:33 AMlinkgrid sample with ListModel/RowRenderer
196guest79.185.142.402vah9ajApr 26, 2014 10:53:57 PMlinkgrid sample with ListModel/RowRenderer
195guest79.185.142.402vah9ajApr 26, 2014 10:53:54 PMlinkgrid sample with ListModel/RowRenderer
194guest79.185.142.402vah9ajApr 26, 2014 10:53:51 PMlinkgrid sample with ListModel/RowRenderer
193guest79.185.142.402vah9ajApr 26, 2014 10:53:48 PMlinkgrid sample with ListModel/RowRenderer
192guest79.185.142.402vah9ajApr 26, 2014 10:53:44 PMlinkgrid sample with ListModel/RowRenderer
191guest79.185.142.402vah9ajApr 26, 2014 10:53:40 PMlinkHierarchy table without using ZK PE/EE
1aaknai151.28.135.2131s871daJul 29, 2013 11:02:46 PMlinkgrid sample with ListModel/RowRenderer
128aaknai151.28.135.2132vah9ajJul 29, 2013 7:20:00 PMlinkuser model to move item to another listbox
1TonyQ114.25.109.94d0n3krApr 21, 2012 10:43:27 AMlinkUsing timer to refresh a grid
1TonyQ220.133.44.3725nk0uiFeb 17, 2012 3:17:34 AMlinkFire a event from child iframe
1TonyQ220.133.44.372eupjotFeb 3, 2012 5:04:52 AMlinkTextbox input restriction sample
1TonyQ72.21.245.2431b3nlr0Dec 20, 2011 10:09:10 AMlinkTest web core taglib in ZUL
1TonyQ198.203.175.175ofqkemDec 17, 2011 3:36:08 AMlinkLatest 10 Fiddles :
constraint binding textbox
3guest172.68.151.16220peldaDec 5, 2025 5:08:19 PMlinkAnother new ZK fiddle
2guest172.68.151.16320peldaDec 5, 2025 5:07:51 PMlinkAnother new ZK fiddle
1guest172.68.151.16220peldaDec 5, 2025 5:07:32 PMlinkAnother new ZK fiddle
1peggypeng172.71.154.99364f4neDec 5, 2025 9:24:31 AMlinktooltip example
2guest104.22.23.13rc1ntoDec 4, 2025 2:23:45 PMlinkAnother new ZK fiddle
1guest172.69.134.2277t7602Dec 4, 2025 1:40:46 PMlinkAnother new ZK fiddle
1peggypeng104.22.17.1802df6e3oDec 4, 2025 8:41:29 AMlinkonClose
1peggypeng172.68.87.248j8kd8aDec 3, 2025 4:10:26 AMlinkAnother new ZK fiddle
1peggypeng172.69.134.2271rm7f4eNov 26, 2025 3:31:24 AMlinkZK-5912-Suggestion
2rebeccalai104.22.20.1442qrmiiuNov 26, 2025 2:07:15 AMlinkAnother new ZK fiddle
6psx36092.241.237.4260fdqNov 7, 2015 11:05:51 AMlinkresources
index.zulzul<?component name="Multiselect" macroURI="Multiselect.zul" class="pkg$.Multiselect"?>
<zk>
<window border="normal" title="hello" apply="org.zkoss.bind.BindComposer" viewModel="@id('vm') @init('pkg$.TestComposer')">
<vlayout>
<label value="Multiselect component. Kind of advanced combobox with autocompletion."/>
<label value="Just two files Multiselect.zul and Multiselect.java, no external dependencies. Copy the files and use the component as shown in the fiddle."/>
<Multiselect id="multiselectControl" model="${vm.fullMultiselectModel}" selectedItems="@bind(vm.selectedItems)"/>
<listbox model="@load(vm.selectedItems)"></listbox>
</vlayout>
</window>
</zk>
TestComposer.javajavaimport org.zkoss.zk.ui.*;
import org.zkoss.zk.ui.event.*;
import org.zkoss.zk.ui.util.*;
import org.zkoss.zk.ui.ext.*;
import org.zkoss.zk.au.*;
import org.zkoss.zk.au.out.*;
import org.zkoss.zul.*;
import org.zkoss.bind.annotation.AfterCompose;
import java.util.*;
public class TestComposer {
private ListModelList<String> fullMultiselectModel = new ListModelList(new ArrayList<String>(), false);
private ListModelList<String> selectedItems = new ListModelList(new ArrayList<String>(), false);
public TestComposer() {
for(int i = 0; i < 20; ++i) {
fullMultiselectModel.add("" + i);
}
}
@AfterCompose
public void doAfterCompose(Component comp) throws Exception {
}
public void onClick$btn(Event e) throws InterruptedException{
Messagebox.show("Hi btn");
}
public ListModelList<String> getFullMultiselectModel() {
return fullMultiselectModel;
}
public void setFullMultiselectModel(ListModelList<String> fullMultiselectModel) {
this.fullMultiselectModel = fullMultiselectModel;
}
public ListModelList<String> getSelectedItems() {
return selectedItems;
}
public void setSelectedItems(ListModelList<String> selectedItems) {
this.selectedItems = selectedItems;
}
}
Multiselect.zulzul
<zk xmlns:h="http://www.w3.org/1999/xhtml" xmlns:w="client">
<div id="wnd" apply="org.zkoss.bind.BindComposer">
<style>
.fieldsTable td {
padding:4px;
}
.z-toolbarbutton {
height:32px;
}
.selectionListbox {
padding:0px;
margin:0px;
posigion:relative;
overflow:hidden;
width:1000px;
height:20px;
}
.selectedItemListbox {
}
.selectedItem {
width:60px;
height:14px;
background-color:#f5f7fa;
display:block;
margin-left:2px;
float:left;
margin-top:3px;
padding-top:2px;
padding-left:2px;
}
.selectedItem:first-child {
margin-left:0;
}
.selectedItemLabel {
width:48px;
height:10px;
display:block;
font-size:8px;
overflow:hidden;
white-space: nowrap;
text-overflow:ellipsis;
}
.selectedItemButton {
padding:0px;
margin-top:1px;
float:left;
}
.selectionWrapper {
width:144px;
overflow:hidden;
position:absolute;
overflow:hidden;
left:3px;
}
</style>
<div style="position:relative">
<!--visible="@load(!mcvm.hideSelectedItems)"-->
<div id="selectionWrapper" sclass="selectionWrapper" >
<h:ul children="@load(mcvm.selectedItems)" class="selectionListbox" id="selectedListbox" >
<template name="children">
<h:li class="selectedItem">
<div style="padding:0px; overflow:hidden;position:relative;">
<label value="${each}" visible="false">
<custom-attributes a="${each}"/>
</label>
<label value="${each}" sclass="selectedItemLabel" style="float:left;"/>
<image width="10px" height="10px"
src="/images/del.png" sclass="selectedItemButton">
<attribute name="onClick"><![CDATA[
Map params = new HashMap();
Label fakelabel = self.getParent().getChildren().get(0);
params.put("item", fakelabel.getAttribute("a"));
BindUtils.postGlobalCommand(null, null, "excludeItem", params);
]]></attribute>
</image>
</div>
</h:li>
</template>
</h:ul>
</div>
</div>
<bandbox id="multiselect" >
<bandpopup id="multiselectPopup">
<div id="multiselectPopupWrapper" style="overflow-y:scroll;overlow-x:hidden;height:100px;" w:onBind="jq(this.$n()).scroll(function(){
var myDiv = jq('$multiselectPopupWrapper')[0];
if (myDiv.offsetHeight + myDiv.scrollTop >= myDiv.scrollHeight) {
zAu.send(new zk.Event(zk.Widget.$('$multiselectPopup'), 'onScrollBottom', {'' : {'data' : {'nodeId': ''}}}, {toServer:true}));
}
})">
<listbox id="multiselectItemsList" fixedLayout="true" model="@load(vm.multiselectModel)" >
</listbox>
</div>
</bandpopup>
</bandbox>
</div>
</zk>
Multiselect.javajavaimport org.zkoss.bind.BindUtils;
import org.zkoss.bind.Binder;
import org.zkoss.bind.DefaultBinder;
import org.zkoss.bind.annotation.*;
import org.zkoss.zhtml.Ul;
import org.zkoss.zk.ui.HtmlMacroComponent;
import org.zkoss.zk.ui.annotation.ComponentAnnotation;
import org.zkoss.zk.ui.event.*;
import org.zkoss.zk.ui.select.annotation.Listen;
import org.zkoss.zk.ui.select.annotation.Wire;
import org.zkoss.zk.ui.util.Clients;
import org.zkoss.zul.*;
import java.util.ArrayList;
import java.util.List;
/**
* Created by phudyakov on 03.11.2015.
*/
@ComponentAnnotation({"model:@ZKBIND(ACCESS=both,SAVE_EVENT=onEdited)", "selectedItems:@ZKBIND(ACCESS=both,SAVE_EVENT=onSelect)"})
public class Multiselect extends HtmlMacroComponent {
private static final long serialVersionUID = 1L;
@Wire("#multiselect")
private Bandbox multiselect;
@Wire("#multiselectItemsList")
private Listbox multiselectItemsList;
@Wire("#multiselectPopup")
private Bandpopup multiselectPopup;
@Wire("#multiselectPopupWrapper")
private Div multiselectPopupWrapper;
@Wire("#selectedListbox")
Ul selectedListbox;
@Wire("#textbox")
private Textbox textbox;
@Wire("#wnd")
private Div window;
@Wire("#selectionWrapper")
private Div selectionWrapper;
private ListModelList multiselectModel = new ListModelList(new ArrayList(), false);
private ListModelList model = new ListModelList(new ArrayList(), false);
private ListModelList selectedItems = new ListModelList(new ArrayList(), false);
private static final int INITIAL_SIZE = 5;
private static final int INCREMENT_SIZE = 3;
private boolean hideSelectedItems;
public Multiselect() {
compose();
}
@Override
public void afterCompose() {
super.afterCompose();
multiselectModel.clear();
multiselectModel.addAll(model.subList(0, Math.min(INITIAL_SIZE, model.size())));
multiselectModel.setMultiple(true);
Multiselect vm = this;
Binder binderOne = new DefaultBinder();
binderOne.init(window, vm, null);
binderOne.setViewModel(vm);
window.setAttribute("vm", vm);
binderOne.addPropertyLoadBindings(multiselectItemsList, "model", "vm.multiselectModel", null, null, null, null, null);
binderOne.addPropertyLoadBindings(selectionWrapper, "visible", "!vm.hideSelectedItems", null, null, null, null, null);
binderOne.addChildrenLoadBindings(selectedListbox, "vm.selectedItems", null, null, null, null, null);
binderOne.addGlobalCommandBinding(window, Events.ON_CLICK, "excludeItem", null);
binderOne.loadComponent(window, true);
multiselect.addEventListener(Events.ON_CHANGING, new EventListener<Event>() {
@Override
public void onEvent(Event event) throws Exception {
multiselectModel.clear();
final InputEvent finalEvent = (InputEvent) event;
List filteredItems = new ArrayList();
for(Object input : model) {
if(input.toString() != null && input.toString().toLowerCase().contains(nullToEmpty(finalEvent.getValue()).toLowerCase())) {
filteredItems.add(input);
}
}
filteredItems.removeAll(selectedItems);
multiselectModel.addAll(filteredItems.subList(0, Math.min(INITIAL_SIZE, filteredItems.size())));
}
});
multiselect.addEventListener(Events.ON_OPEN, new EventListener<Event>() {
@Override
public void onEvent(Event event) throws Exception {
final OpenEvent finalEvent = (OpenEvent) event;
hideSelectedItems = finalEvent.isOpen();
BindUtils.postNotifyChange(null, null, Multiselect.this, "hideSelectedItems");
}
});
multiselectPopup.addEventListener("onScrollBottom", new EventListener<Event>() {
@Override
public void onEvent(Event event) throws Exception {
moreItems();
}
});
multiselectItemsList.addEventListener(Events.ON_SELECT, new EventListener<Event>() {
@Override
public void onEvent(Event event) throws Exception {
SelectEvent selectEvent = (SelectEvent) event;
multiselect.close();
Object selectedValue = selectEvent.getSelectedObjects().iterator().next();
selectedItems.add(selectedValue);
multiselectModel.remove(selectedValue);
hideSelectedItems = false;
BindUtils.postNotifyChange(null, null, Multiselect.this, "hideSelectedItems");
BindUtils.postNotifyChange(null, null, Multiselect.this, "multiselectModel");
BindUtils.postNotifyChange(null, null, Multiselect.this, "selectedItems");
Clients.evalJavaScript(
"var myDiv = jq('$multiselectPopupWrapper')[0];"+
"if (myDiv.offsetHeight + myDiv.scrollTop >= myDiv.scrollHeight) {"+
"zAu.send(new zk.Event(zk.Widget.$('$multiselectPopup'), 'onScrollBottom', {'' : {'data' : {'nodeId': ''}}}, {toServer:true}));" +
"}");
Events.postEvent("onSelect", Multiselect.this, null);
}
});
}
@GlobalCommand
public void excludeItem(@BindingParam("item") Object item) {
selectedItems.remove(item);
if(!multiselectModel.contains(item)) {
multiselectModel.add(0, item);
}
BindUtils.postNotifyChange(null, null, this, "multiselectModel");
BindUtils.postNotifyChange(null, null, this, "selectedItems");
}
@Command
public void moreItems() {
List diff = new ArrayList();
diff.addAll(model);
diff.removeAll(multiselectModel);
diff.removeAll(selectedItems);
multiselectModel.addAll(diff.subList(0, Math.min(diff.size(), INCREMENT_SIZE)));
}
@Listen("onFocus = #multiselect")
public void focusBandbox() {
// multiselect.open();
}
public ListModelList getMultiselectModel() {
return multiselectModel;
}
public void setMultiselectModel(ListModelList multiselectModel) {
this.multiselectModel = multiselectModel;
}
public Bandbox getMultiselect() {
return multiselect;
}
public void setMultiselect(Bandbox multiselect) {
this.multiselect = multiselect;
}
public ListModelList getSelectedItems() {
return selectedItems;
}
public void setSelectedItems(ListModelList selectedItems) {
this.selectedItems = selectedItems;
multiselectModel = new ListModelList(new ArrayList(), false);multiselectModel.clear();
List filteredItems = new ArrayList();
for(Object input : model) {
if(input.toString() != null && input.toString().toLowerCase().contains(nullToEmpty(multiselect.getValue()).toLowerCase())) {
filteredItems.add(input);
}
}
filteredItems.removeAll(selectedItems);
multiselectModel.addAll(filteredItems.subList(0, Math.min(INITIAL_SIZE, filteredItems.size())));
BindUtils.postNotifyChange(null, null, Multiselect.this, "multiselectModel");
BindUtils.postNotifyChange(null, null, Multiselect.this, "selectedItems");
}
private static String nullToEmpty(String s) {
return s != null ? s : "";
}
public boolean isHideSelectedItems() {
return hideSelectedItems;
}
public void setHideSelectedItems(boolean hideSelectedItems) {
this.hideSelectedItems = hideSelectedItems;
}
public Listbox getMultiselectItemsList() {
return multiselectItemsList;
}
public void setMultiselectItemsList(Listbox multiselectItemsList) {
this.multiselectItemsList = multiselectItemsList;
}
public Bandpopup getMultiselectPopup() {
return multiselectPopup;
}
public void setMultiselectPopup(Bandpopup multiselectPopup) {
this.multiselectPopup = multiselectPopup;
}
public Div getMultiselectPopupWrapper() {
return multiselectPopupWrapper;
}
public void setMultiselectPopupWrapper(Div multiselectPopupWrapper) {
this.multiselectPopupWrapper = multiselectPopupWrapper;
}
public ListModelList getModel() {
return model;
}
public void setModel(ListModelList model) {
this.model = model;
}
public Textbox getTextbox() {
return textbox;
}
public void setTextbox(Textbox textbox) {
this.textbox = textbox;
}
public Div getWindow() {
return window;
}
public void setWindow(Div window) {
this.window = window;
}
public Div getSelectionWrapper() {
return selectionWrapper;
}
public void setSelectionWrapper(Div selectionWrapper) {
this.selectionWrapper = selectionWrapper;
}
}