Processing...
Description & Source Code
  • Description
  • View
  • Controller
  • Model
    Accessories.java
    Car.java
    CarData.java
    CarService.java

In this demo we'll walk through a component set that allows users to make single or multiple selections from a checklist or drop-down menu.


Access Controller's Variables in View

We may access variables in the controller from view by the use of an EL Expression: ${expression} . The implicit variable win$composer is a reference to the controller which was assigned to the Window component with the ID: win. For instance, to assign the component attribute value with the property name of a car instance in the controller, we write value="${win$composer.car.name}".


Radio and Radiogroup

A set of Radio buttons forms a Radiogroup that prompts users to make a single selection among the available options. A default selection can be made by specifying a Radio button's selected attribute.

<radiogroup id="transmissionRadiogroup">
	<radio id="automaticRadio" label="Automatic" selected="${win$composer.car.autoTransmission}" />
	<radio id="manualRadio" label="Manual" ... />
</radiogroup>

We can register an onCheck event listener to a Radiogroup and whenever a selection is made, the selected item can be retrieve by calling the getSelectedItem method of Radiogroup.

public class EditController ...{
	@Wire
	private Radiogroup transmissionRadiogroup;
	
	@Listen("onCheck = #transmissionRadiogroup")
	public void changeTransmission() {
		Radio selectedItem = transmissionRadiogroup.getSelectedItem();
		...
	}
}

Checkbox

An array of Checkbox components can be put together as a mean to select multiple items; unlike Radio buttons wrapped in a Radiogroup which allows only a single selection. The default status of a Checkbox can be set using its checked attribute.

<checkbox id="absCheckbox" label="ABS" checked="${win$composer.car.accessories.abs}" />

Similar to a Radio component, we register an onCheck event listener to Checkbox to be notified of a state change.To get the state of a Checkbox, we call its isChecked() method.


Model Usage

Most selection/drop-down components support the use of models (i.e. ListModel<E> ) to load or store data. When we assign a model to a component using the EL expression as shown in the snippet below, we're in effect calling the controller's getSalesmenModel() method.

				<listbox id="salesmenListbox" model="${win$composer.salesmenModel}" />

We can enable the multiple selection feature by invoking the setMultiple(boolean) method on the model class. Note that we're enabling multiple selection on the data model, as oppose to setting multiple="true" on the component itself.

public class EditController ...{
	private Car car;
	private ListModel<String> salesmenModel = new ListModelList<String>(CarData.getSalesmen());

	public EditController() {
		...
		((ListModelList<String>)salesmenModel).setMultiple(true);
		...
	}
	
	public ListModel<String> getSalesmenModel() {
		return salesmenModel;
	}
}

Selectbox

Selectbox is a lightweight drop-down list and supports only a single selection.

To know which one has been selected, we attach an onSelect event listener to Selectbox and retrieve the selection through the getSelection() method of the model.

<selectbox id="typesSelectbox" model="${win$composer.typesModel}" >
	<template name="model">
		<label value="${each}" />
	</template>
</selectbox>

The <template> tag generates components iteratively and the implicit object each references to each item being iterated in the model.


Combobox

Combobox is a special text input component that embeds a drop-down list and supports auto-complete feature. When the attribute autodrop="true" is assigned to a Combobox, its list is dropped down automatically when an input is entered by a user.

To obtain the value of a Combobox when it's modified, we attach an onChange event listener to it and retrieve its value through the getValue() method.

<combobox id="countriesCombobox" model="${win$composer.countriesModel}" autodrop="true">
	<template name="model">
		<comboitem label="${each}" />
	</template>
</combobox>

Listbox

Listbox is a feature rich component that can serve as an items list which allows multiple selection. When the attribute checkmark="true" is assigned to a Listbox, it will display a checkbox or radio button at the header of each list item.

To obtain the set of selected items in a Listbox, we attach an onSelect event listener to the Listbox and retrieve the selected items by calling the getSelection() method on the model.

<listbox id="salesmenListbox" model="${win$composer.salesmenModel}" checkmark="true">
	<template name="model">
		<listitem label="${each}" />
	</template>
</listbox>
demo.zul
<window id="win" title="Car Editor" width="400px" border="normal"
	apply="demo.getting_started.selection_dropdown.EditController">
	<grid>
		<columns>
			<column width="100px" />
			<column />
		</columns>
		<rows>
			<row>
				Model:
				<label value="${win$composer.car.model}" />
			</row>
			<row>
				Transmission:
				<radiogroup id="transmissionRadiogroup">
					<hlayout>
						<radio id="automaticRadio" label="Automatic"
							selected="${win$composer.car.autoTransmission}" />
						<radio id="manualRadio" label="Manual"
							selected="${not win$composer.car.autoTransmission}" />
					</hlayout>
				</radiogroup>
			</row>
			<row>
				Accessories:
				<hlayout id="accessories">
					<checkbox id="absCheckbox" label="ABS"
						checked="${win$composer.car.accessories.abs}" />
					<checkbox id="airbagCheckbox" label="Airbag"
						checked="${win$composer.car.accessories.airbag}" />
					<checkbox id="gpsCheckbox" label="GPS"
						checked="${win$composer.car.accessories.gps}" />
					<checkbox id="keylessCheckbox" label="Keyless"
						checked="${win$composer.car.accessories.keyless}" />
				</hlayout>
			</row>
			<row>
				Type:
				<selectbox id="typesSelectbox" model="${win$composer.typesModel}" >
					<template name="model">
						<label value="${each}" />
					</template>
				</selectbox>
			</row>
			<row>
				Origin:
				<combobox id="countriesCombobox" model="${win$composer.countriesModel}"
					autodrop="true">
					<template name="model">
						<comboitem label="${each}" />
					</template>
				</combobox>
			</row>
			<row valign="top">
				Salesmen:
				<listbox id="salesmenListbox" model="${win$composer.salesmenModel}"
					checkmark="true">
					<template name="model">
						<listitem label="${each}" />
					</template>
				</listbox>
			</row>
		</rows>
	</grid>
	<button id="submitButton" label="Submit" />
</window>
EditController.java
package demo.getting_started.selection_dropdown;

import java.util.Set;
import org.zkoss.zk.ui.Component;
import org.zkoss.zk.ui.event.CheckEvent;
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.Clients;
import org.zkoss.zul.Checkbox;
import org.zkoss.zul.Combobox;
import org.zkoss.zul.ListModel;
import org.zkoss.zul.ListModelList;
import org.zkoss.zul.Listbox;
import org.zkoss.zul.Radio;
import org.zkoss.zul.Radiogroup;
import org.zkoss.zul.Selectbox;
import org.zkoss.zul.Window;
import demo.getting_started.Accessories;
import demo.getting_started.Car;
import demo.getting_started.CarData;
import demo.getting_started.CarService;
import demo.getting_started.CarServiceImpl;

public class EditController extends SelectorComposer<Component> {
	private static final long serialVersionUID = 1L;

	private CarService carService = new CarServiceImpl();
	private Car car;
	private ListModel<String> typesModel = new ListModelList<String>(CarData.getTypes());
	private ListModel<String> countriesModel = new ListModelList<String>(CarData.getCountries());
	private ListModel<String> salesmenModel = new ListModelList<String>(CarData.getSalesmen());

	@Wire
	private Window win;
	@Wire
	private Radiogroup transmissionRadiogroup;
	@Wire
	private Checkbox absCheckbox;
	@Wire
	private Checkbox airbagCheckbox;
	@Wire
	private Checkbox gpsCheckbox;
	@Wire
	private Checkbox keylessCheckbox;
	@Wire
	private Selectbox typesSelectbox;
	@Wire
	private Combobox countriesCombobox;
	@Wire
	private Listbox salesmenListbox;

	public EditController() {
		// initialize data
		car = carService.findAll().get(0);

		// set default selection
		((ListModelList<String>)typesModel).addToSelection(car.getType());
		((ListModelList<String>)countriesModel).addToSelection(car.getCountry());
		((ListModelList<String>)salesmenModel).setMultiple(true);
		for(String salesman : car.getSalesmen())
			((ListModelList<String>)salesmenModel).addToSelection(salesman);
	}

	public Car getCar() {
		return car;
	}

	public ListModel<String> getTypesModel() {
		return typesModel;
	}

	public ListModel<String> getCountriesModel() {
		return countriesModel;
	}

	public ListModel<String> getSalesmenModel() {
		return salesmenModel;
	}

	@Listen("onCheck = #transmissionRadiogroup")
	public void changeTransmission() {
		Radio selectedItem = transmissionRadiogroup.getSelectedItem();
		car.setAutoTransmission("automaticRadio".equals(selectedItem.getId()));

		showNotify("Changed to: " + selectedItem.getLabel(), transmissionRadiogroup.getParent());
	}

	@Listen("onCheck = #accessories > checkbox")
	public void changeAccessory(CheckEvent event) {
		Accessories accessories = car.getAccessories();
		accessories.setAbs(absCheckbox.isChecked());
		accessories.setAirbag(airbagCheckbox.isChecked());
		accessories.setGps(gpsCheckbox.isChecked());
		accessories.setKeyless(keylessCheckbox.isChecked());

		showNotify("Changed to: " + accessories, absCheckbox.getParent());
	}

	@Listen("onSelect = #typesSelectbox")
	public void changeType() {
		Set<String> types = ((ListModelList<String>)typesModel).getSelection();
		String type = types.iterator().next();
		car.setType(type);
		showNotify("Changed to: " + type, typesSelectbox);
	}

	@Listen("onChange = #countriesCombobox")
	public void changeCountry() {
		String country = countriesCombobox.getValue();

		if(((ListModelList<String>)countriesModel).contains(country)) {
			car.setCountry(country);
			showNotify("Changed to: " + country, countriesCombobox);
		} else {
			showNotify("Unknow country : " + country, countriesCombobox);
		}
	}

	@Listen("onSelect = #salesmenListbox")
	public void changeSalesmen() {
		Set<String> salesmen = ((ListModelList<String>)salesmenModel).getSelection();
		car.setSalesmen(salesmen);

		showNotify("Changed to: " + salesmen, salesmenListbox);
	}

	@Listen("onClick = #submitButton")
	public void submit() {
		carService.store(car);

		showNotify("Saved", win);
	}

	private void showNotify(String msg, Component ref) {
		Clients.showNotification(msg, "info", ref, "end_center", 2000);
	}
}
Accessories.java
package demo.getting_started;

public class Accessories {
	boolean abs;
	boolean airbag;
	boolean gps;
	boolean keyless;

	public Accessories() {
	}

	public Accessories(boolean abs, boolean airbag, boolean gps, boolean keyless) {
		this.abs = abs;
		this.airbag = airbag;
		this.gps = gps;
		this.keyless = keyless;
	}

	public boolean isAbs() {
		return abs;
	}

	public void setAbs(boolean abs) {
		this.abs = abs;
	}

	public boolean isAirbag() {
		return airbag;
	}

	public void setAirbag(boolean airbag) {
		this.airbag = airbag;
	}

	public boolean isGps() {
		return gps;
	}

	public void setGps(boolean gps) {
		this.gps = gps;
	}

	public boolean isKeyless() {
		return keyless;
	}

	public void setKeyless(boolean keyless) {
		this.keyless = keyless;
	}

	public String toString() {
		StringBuilder sb = new StringBuilder();
		if(abs)
			sb.append(", ABS");
		if(airbag)
			sb.append(", Airbag");
		if(gps)
			sb.append(", GPS");
		if(keyless)
			sb.append(", Keyless");
		if(sb.length() <= 0)
			sb.append("None");
		else
			sb.delete(0, 2);
		return sb.toString();
	}
}
Car.java
package demo.getting_started;

import java.util.Set;

public class Car {

	private String carId;
	private String model;
	private String picture;
	private String make;
	private String country;
	private String type;
	private double cost;
	private int engineDisplacement;
	private boolean autoTransmission;
	private Accessories accessories;
	private Set<String> salesmen;

	public Car() {
	}

	public String getCarId() {
		return carId;
	}

	public void setCarId(String carId) {
		this.carId = carId;
	}

	public String getModel() {
		return model;
	}

	public void setModel(String model) {
		this.model = model;
	}

	public String getPicture() {
		return picture;
	}

	public void setPicture(String picture) {
		this.picture = picture;
	}

	public String getMake() {
		return make;
	}

	public void setMake(String make) {
		this.make = make;
	}

	public String getCountry() {
		return country;
	}

	public void setCountry(String country) {
		this.country = country;
	}

	public String getType() {
		return type;
	}

	public void setType(String type) {
		this.type = type;
	}

	public double getCost() {
		return cost;
	}

	public void setCost(double cost) {
		this.cost = cost;
	}

	public int getEngineDisplacement() {
		return engineDisplacement;
	}

	public void setEngineDisplacement(int engineDisplacement) {
		this.engineDisplacement = engineDisplacement;
	}

	public boolean isAutoTransmission() {
		return autoTransmission;
	}

	public void setAutoTransmission(boolean autoTransmission) {
		this.autoTransmission = autoTransmission;
	}

	public Accessories getAccessories() {
		return accessories;
	}

	public void setAccessories(Accessories accessories) {
		this.accessories = accessories;
	}

	public Set<String> getSalesmen() {
		return salesmen;
	}

	public void setSalesmen(Set<String> salesmen) {
		this.salesmen = salesmen;
	}

	public String toString() {
		return model;
	}
}
CarData.java
package demo.getting_started;

import java.util.Arrays;
import java.util.List;

public class CarData {

	public static List<String> getAccessories() {
		return Arrays.asList(new String[]{"ABS", "Airbag", "GPS", "Keyless"});
	}

	public static List<String> getCountries() {
		return Arrays.asList(new String[]{"China", "France", "Germany", "Italy", "Japan", "Korea", "Sweden",
				"Taiwan", "United Kingdom", "United States"});
	}

	public static List<String> getSalesmen() {
		return Arrays.asList(new String[]{"Adam", "Brian", "Cary", "Danny", "Edward", "Franklin", "Geroge"});
	}

	public static List<String> getTypes() {
		return Arrays.asList(new String[]{"MPV", "SUV", "Sedan", "Sport", "Supercar", "Van"});
	}

}
CarService.java
package demo.getting_started;

import java.util.List;

public interface CarService {

	/**
	 * Retrieve all cars in the car store.
	 * @return all cars.
	 */
	public List<Car> findAll();

	/**
	 * Store or modify a car in car store.
	 */
	void store(Car car);

	/**
	 * Store or modify a inventory item in car store.
	 */
	void store(InventoryItem inventoryItem);

	/**
	 * Order cars.
	 */
	void order(List<OrderItem> orderItems);

	/**
	 * Retrieve the root of car categories.
	 */
	Category getCarCategoriesRoot();

	/**
	 * Count cars by filter.
	 */
	int countByFilter(String filter);

	/**
	 * Query cars by filter.
	 */
	List<Car> queryByFilter(String filter);
}