Ajax without JavaScript
Tutorial - Introducing ZK - Part 2
Controller & databinding
This section provides a step by step guide of the Controller and its functions. The controller handles all the business logic of the application and responds to events fired from the user interface. Currently our sample application includes add, update and delete events for both the employees and the departments.
Defining a Controller
To create a controller the class org.zkoss.zk.ui.util.GenericForwardComposer should be extended. An example controller is shown in Figure 3. The composer then needs to be associated with a relevant view. Previously, the usage of apply was touched upon in Nesting ZK Components. In the following section the relationship is outlined in more detail.
Figure 3: Example Controller
public class EmployeeController extends GenericForwardComposer {
/**
*
*/
private static final long serialVersionUID = -9089818718875587898L;
}
Associating the Controller with the view
To implement the interaction between the View and Controller, data binding is used in this example. To implement data binding, the apply attribute of a component has to be set. Most components support the apply attribute. Figure 4 demonstrates the usage of the apply attribute. The EmployeeController is responsible for handling the user flow. The code of the EmployeeController is demonstrated in Figure 5. Figure 5 introduces two concepts – firstly the ability to capture an event and secondly invalidating a component. These are outlined next.
Figure 4: A part of index.zul
<div id="employeediv" apply="org.zkoss.jtjexample.controller.EmployeeController" hflex="true">
Figure 5: EmployeeController.java
public class EmployeeController extends GenericForwardComposer {
/**
*
*/
private static final long serialVersionUID = -9089818718875587898L;
private static final Log log = Log.lookup(EmployeeController.class);
private Employee _currentEmployee;
private ListModelList _model = EmployeeService.INSTANCE.getModel();
Listbox lstEmployee;
Textbox txtFirstName, txtLastName;
Intbox intAge;
public Employee getCurrentEmployee() {
return _currentEmployee;
}
public void setCurrentEmployee(Employee currentEmployee) {
this._currentEmployee = currentEmployee;
}
public ListModel getEmployeeModel() {
return _model;
}
// click events
public void onClick$btnAddEmployee() {
String firstName = txtFirstName.getText();
String lastName = txtLastName.getText();
int iAge = Integer.parseInt(intAge.getText());
Employee employee = new Employee(firstName, lastName, iAge);
if (!_model.add(employee)) {
reportError(Messages.getString("EmployeeController.0"), employee);
}
}
public void onClick$btnUpdateEmployee() {
if (lstEmployee.getSelectedItem() != null) {
Employee employee = (Employee) (lstEmployee.getSelectedItem()
.getValue());
employee.setFirstName(txtFirstName.getText());
employee.setLastName(txtLastName.getText());
employee.setAge(Integer.parseInt(intAge.getText()));
} else {
UiUtils.showMessage(Messages.getString("EmployeeController.2"));
}
}
public void onClick$btnDeleteEmployee() {
if (lstEmployee.getSelectedItem() != null) {
Employee employee = (Employee) (lstEmployee.getSelectedItem()
.getValue());
if (!_model.remove(employee)) {
reportError(Messages.getString("EmployeeController.3"), employee);
}
} else {
UiUtils.showMessage(Messages.getString("EmployeeController.4"));
}
}
private void reportError(String message, Employee employee) {
StringBuilder sb = new StringBuilder(message).append(Messages.getString("EmployeeController.5")).append(employee);
final String error = sb.toString();
UiUtils.showMessage(error);
log.error(error);
}
}
Capturing events
Event capturing in ZK is easy to implement, providing developers with enormous power. Figure 6 is a function signature to capture the onClick event from the button named btnAddEmployee. The onClick event is fired when a user clicks a button. The method signature in Figure 6 can be broken down into 3 parts. Firstly, the return type is void and method is public. The method name consists of the event name, followed by a dollar sign ($) and the name of the component whose event you want to trap. Then lastly, in this case the event type is a ForwardEvent. Using this technique it is possible to trap any event from any ZK component in a composer which is properly wired to the view.
Figure 6: Function signature for event capturing
public void onClick$btnAddEmployee(ForwardEvent fe)
Using databinding to load data from our service
The view is tied to the controller using the apply attribute as discussed in Associating the Controller with the view. Now ZK's data binding mechanism needs to be activated for this page. Remember, due to the include mode being deferred each zul is considered a separate entity, thus, they can each have their own data binding instance. To initialize the Annotated data binder, use the line shown in Figure 7.
Figure 7:Initalise the databinder
<?init class="org.zkoss.zkplus.databind.AnnotateDataBinderInit"?>

Follow us