Recently I had the following requirements for a ZK Listbox:
- Right click menu [ options dynamic based on properties of the object backing the row selected ]
- Be able to select multiple rows (for deletion) with checkboxes
The listbox started out without having the multi-select option. So initially I had a backing “selectedItem” property in my backing ViewModel. Since I built up my dynamic right-click menu as well in this ViewModel, in order to access properties of the row selected, it was just a matter of reading them off the selectedItem property in my view model.
So for example my Listbox initially was set up with
<listbox id="executionsList" model="@load(vm.executions)"
selectedItems="@bind(vm.selectedExecution)" ... />
When building my right-click menu in my ViewModel, I just read what I needed from the bound “selectedExecution”
However, once I needed to introduce the multi-select options, things became a bit uglier. To setup a listbox for multi-select (with checkboxes) you add both the following properties to your listbox: checkmark=”true” multiple=”true”
But you’ll also need to keep track of the multi select items so you’ll need the selectedItems property as well. So something like:
<listbox id="executionsList" model="@load(vm.executions)"
selectedItems="@bind(vm.selectedExecutions)"
checkmark="true" multiple="true">
Things became buggy, however, when I also wanted the ‘selectedItem’ property on the listbox for use with my right-click option. Without getting into the details of what went wrong using both selectedItem and selectedItems, I opted to just get rid of having right-click trigger the row being selected and handled retrieving the row directly in the right-click menupopup method defined in my ViewModel. This gave me a ‘decent’ approach: multi-select worked as expected, and right-click ONLY handled the row that was being right-clicked on (and it did NOT trigger the row being selected for multi-select.)
So here is what was done from a code perspective:
The ZK listbox relevant info:
<listbox id="executionsList" model="@load(vm.executions)"
selectedItems="@bind(vm.selectedExecutions)"
checkmark="true" multiple="true">
<listhead sizable="true">
<!-- not shown for brevity -->
</listhead>
<template name="model" var="item">
<listitem
onRightClick="@command('getExecMenuPopup', target=event.target, execution=item)">
In order to disable having right-click trigger the row selection, add the following somewhere on the page before your listbox
<custom-attributes org.zkoss.zul.listbox.rightSelect="false"/>
or if you want it global, in your zk.xml file add:
<library-property>
<name>org.zkoss.zul.listbox.rightSelect</name>
<value>false</value>
</library-property>
In my ViewModel I built up my menupopup…
@Command
public void getExecMenuPopup(@BindingParam("target") Component target, @BindingParam("execution") final Execution content) {
Menupopup menuPopup = new Menupopup();
menuPopup.setPage(target.getPage());
menuPopup.setWidth("150");
Menuitem viewSpec = new Menuitem("View Details [ "+execution.getId()+" ]");
viewSpec.addEventListener("onClick", new EventListener() {
public void onEvent(Event evt) throws Exception {
viewDetails(content);
}
});
menuPopup.appendChild(viewSpec);
//other items