Processing...
Description & Source Code

ZK Cascader selects a value from a hierarchy. Note that the selectedItem is null before the leaf item is selected.

Cascader is useful for multi-level selection cases such as selecting Country - State - City.

cascader.zul
<zk>
	<div apply="demo.combobox.cascader.CascaderComposer">
		<cascader id="cascader" width="360px"/>
		<separator/>
		<button id="selectNodeInModel" label="Select 'Node 2.3' in Model"/>
	</div>
</zk>
CascaderComposer.java
package demo.combobox.cascader;

import demo.combobox.cascader.CascaderData.MyNodeData;
import org.zkoss.util.Converter;
import org.zkoss.zk.ui.Component;
import org.zkoss.zk.ui.event.OpenEvent;
import org.zkoss.zk.ui.event.SelectEvent;
import org.zkoss.zk.ui.select.SelectorComposer;
import org.zkoss.zk.ui.select.annotation.Listen;
import org.zkoss.zk.ui.select.annotation.Wire;
import org.zkoss.zk.ui.util.Notification;
import org.zkoss.zkmax.zul.Cascader;
import org.zkoss.zul.DefaultTreeModel;
import org.zkoss.zul.ItemRenderer;
import org.zkoss.zul.TreeNode;

import java.util.Collection;
import java.util.stream.Collectors;

public class CascaderComposer extends SelectorComposer {

	@Wire
	private Cascader cascader;
	private DefaultTreeModel<MyNodeData> model;

	@Override
	public void doAfterCompose(Component comp) throws Exception {
		super.doAfterCompose(comp);
		cascader.setPlaceholder("select your node");
		model = CascaderData.buildModel();
		cascader.setModel(model);
		cascader.setItemRenderer(itemRenderer());
		cascader.setItemConverter(itemConverter());
	}

	private Converter<Collection<TreeNode<MyNodeData>>, String> itemConverter() {
		return nodePath -> nodePath.stream()
				.map(node -> node.getData().getLabel())
				.collect(Collectors.joining(" > "));
	}

	private ItemRenderer<TreeNode<MyNodeData>> itemRenderer() {
		return (component, data, i) ->
				data.getData().getLabel();
	}

	@Listen("onClick=#selectNodeInModel")
	public void onSelectNodeInModel() {
		model.addSelectionPath(new int[]{1, 2});
	}

	@Listen("onSelect=#cascader")
	public void onCascaderSelect(SelectEvent event) {
		Notification.show("selected item: " +
				event.getSelectedObjects() +
				"<br/><br/>" +
				"selected path: " +
				cascader.getSelectedItems());
	}

}
CascaderData.java
package demo.combobox.cascader;

import org.zkoss.zul.DefaultTreeModel;
import org.zkoss.zul.DefaultTreeNode;

import java.util.List;

import static java.util.Arrays.asList;

public class CascaderData {

	public static DefaultTreeModel<MyNodeData> buildModel() {
		return new DefaultTreeModel<>(node("root", asList(
				node("Node-1"),
				node("Node-2", asList(
						node("Node-2.1"),
						node("Node-2.2", asList(
								node("Node-2.2.1"),
								node("Node-2.2.2"),
								node("Node-2.2.3"),
								node("Node-2.2.4"),
								node("Node-2.2.5"))
						),
						node("Node-2.3", asList(
								node("Node-2.3.1"),
								node("Node-2.3.2", asList(
										node("Node-2.3.2.1"),
										node("Node-2.3.2.2"))
								),
								node("Node-2.3.3"))
						),
						node("Node-2.4"))
				),
				node("Node-3"),
				node("Node-4"))
		));
	}

	private static DefaultTreeNode<MyNodeData> node(String label) {
		return new DefaultTreeNode<>(new MyNodeData(label));
	}

	private static DefaultTreeNode<MyNodeData> node(String label, List<DefaultTreeNode<MyNodeData>> children) {
		return new DefaultTreeNode<>(new MyNodeData(label), children);
	}

	public static class MyNodeData {
		private final String label;

		public MyNodeData(String label) {
			this.label = label;
		}

		public String getLabel() {
			return label;
		}

		@Override
		public String toString() {
			return "MyNodeData{" +
					"label='" + label + '\'' +
					'}';
		}
	}

}