Processing...
Description & Source Code

A Listbox allows users to select one or more items from a list in a tabular format. In this demo we'll see how Listbox handles selection, how to distribute overflowed list items into pages, and how to sort data in Listbox.


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 model with the a data model called carsModel in the controller, we write model="${win$composer.carsModel}".


Model Usage

When we access Listbox data through a data model such as ListModelList using the EL expression as shown in the snippet below, we're in effect calling the controller's getCarsModel() method.

We can embed text and image directly in Listcell by assigning value to its label and image attributes respectively. The number of Listcell contained in a Listitem should equal to the number of Listheader components.

<listbox model="${win$composer.carsModel}" ...>
	<listhead>
		...
		<listheader label="Transmission" ... />
		<listheader label="Country" ... />
	</listhead>
	<template name="model">
		<listitem>
			...
			<listcell label="${each.autoTransmission ? 'AT' : 'MT'}"
				image="/.../${each.autoTransmission ? 'at' : 'mt' }.png" />
			<listcell ...>
				<image src="/.../${each.country}.png" />
				<label value="${each.country}" />
			</listcell>
		</listitem>
	</template>
</listbox>

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


Selection

The ability to allow users to select single or multiple items is the main distinction between Listbox and Grid. To enable multiple selection, we should call the setMultiple(boolean) method on the model, not on the Listbox component.

public class ListboxController ...{
	private ListModel<Car> carsModel;

	public ListboxController() {
		CarService carService = ...
		carsModel = new ListModelList<Car>(carService.findAll());
		((ListModelList<Car>)carsModel).setMultiple(true);
	}
}

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.

<listbox ... checkmark="true" ...>

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.


Paging

Paging allows overflowed items to be shown in subsequent pages. To enable a Listbox's built in paging feature, simply assign the attribute mold="paging". The pageSize attribute is used to control the number of rows allowed per page (default is 20). Alternatively, we can set autopaging="true" so the number of rows will be determined by the available vertical space in Grid. For a complete discussion on Grid's paging features, please see reference.

<listbox ... mold="paging" pageSize="9">

Sorting

Listbox has built in sorting functionalities. To enable sorting, simply assign a Listhead's attribute sort="auto". auto accepts arguments as keys for sorting. For example, for a data model containing a list of individuals, the property make may be used to sort the list as such: auto(make). Hence, when users click the header of this particular column, Listbox would sort the rows by individual's name.

<listheader label="Make" align="center" sort="auto(make)" />

We may also instruct the Listbox to sort in an ascending or descending manner. Please consult: here

demo.zul
<window id="win" title="Car List" border="normal"
	apply="demo.getting_started.listbox.ListboxController">
	<listbox model="${win$composer.carsModel}" checkmark="true" mold="paging" pageSize="9">
		<listhead>
			<listheader width="32px" />
			<listheader label="Model" align="center" sort="auto(model)" />
			<listheader label="Make" align="center" sort="auto(make)" />
			<listheader label="Type" align="center" sort="auto(type)" />
			<listheader label="Cost" align="center" sort="auto(cost)"
				image="/widgets/getting_started/img/dollar.png" />
			<listheader label="Displacement" align="center" sort="auto(engineDisplacement)" />
			<listheader label="Transmission" align="center" />
			<listheader label="Country" align="center" sort="auto(country)" width="130px" />
		</listhead>
		<template name="model">
			<listitem>
				<listcell />
				<listcell label="${each.model}" />
				<listcell label="${each.make}" />
				<listcell label="${each.type}" />
				<listcell label="${each.cost}" style="text-align: right"/>
				<listcell label="${each.engineDisplacement} c.c." style="text-align: right"/>
				<listcell label="${each.autoTransmission ? 'AT' : 'MT'}"
					image="/widgets/getting_started/img/${each.autoTransmission ? 'at' : 'mt' }.png" />
				<listcell style="text-align: left">
					<image src="/widgets/getting_started/img/${each.country}.png" />
					<label value="${each.country}" />
				</listcell>
			</listitem>
		</template>
	</listbox>
</window>
ListboxController.java
package demo.getting_started.listbox;

import java.util.Set;
import org.zkoss.zk.ui.Component;
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.ListModel;
import org.zkoss.zul.ListModelList;
import org.zkoss.zul.Window;
import demo.getting_started.Car;
import demo.getting_started.CarService;
import demo.getting_started.CarServiceImpl;

public class ListboxController extends SelectorComposer<Component> {

	private static final long serialVersionUID = 1L;

	private ListModel<Car> carsModel;

	@Wire
	private Window win;
	
	public ListboxController() {
		CarService carService = new CarServiceImpl();
		carsModel = new ListModelList<Car>(carService.findAll());
		((ListModelList<Car>)carsModel).setMultiple(true);
	}

	public ListModel<Car> getCarsModel() {
		return carsModel;
	}

	@Listen("onSelect = listbox")
	public void updateMessage() {
		Set<Car> selectedCars = ((ListModelList<Car>)carsModel).getSelection();
		int size = selectedCars.size();
		
		showNotify(size > 0 ? size + " cars selected: " + selectedCars : "no car selected", win);
	}
	
	private void showNotify(String msg,Component ref){
		Clients.showNotification(msg,"info",ref,"top_right",2000);
	}
}
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;
	}
}
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);
}