Implementing the view
In this section, you will learn about the planning and implementation of the GUI using the vast array of Ajax controls provided by ZK.
The ZK framework uses ZUML markup to describe GUIs, and stores markup within *.zul files. ZUML is a powerful concept that enables developers to rapidly implement complex GUIs. In the following sections, you will see how to use ZUML to implement powerful interfaces.
Most people are familiar with markup languages due to the extensive use of both HTML and XML, so ZK’s ZUML should instantly have a familiar feel. Firstly, a simple window is defined.
Listing 7. Simple zul file
<window id="win" title="Welcome to the employee demo!" border="normal" apply="org.zkforge.controllers.MainController"> </window>
As shown in Listing 7, attributes
are used to set certain properties of the window. The
id attribute is ZK’s reference to the
title sets the text, and
border sets the window’s border type.
One of the most powerful concepts in ZK is its component model. The model affords developers the ability to place components inside each other. Generally, the majority of components in ZK can be children of any other components. This is called the nesting of components.
In this example it is better to split the functionality between departments and employees, and not have the two areas overlap. Therefore an easy method of separation is needed while enabling one to switch back and forth quickly.
Luckily ZK has hundreds of components to choose from. In this instance, it would seem like a tabbox would work best. Therefore the tabbox is nested inside the window as demonstrated in Listing 8.
Listing 8. Nested components
<?page title="Welcome to the employee demo!" contentType="text/html;charset=UTF-8"?> <window id="win" title="Welcome to the employee demo!" border="normal" apply="org.zkforge.controllers.MainController"> <tabbox hflex="true" id="tbTabs"> <tabs> <tab label="Employees" /> <tab label="Departments" /> </tabs> <tabpanels> <tabpanel> </tabpanel> <tabpanel> </tabpanel> </tabpanels> </tabbox> </window>
The output of Listing 8 is shown in Figure 1.
Figure 1. Main.zul output
A couple of concepts need to be highlighted here. First, an observer will notice the apply attribute for the window and an hflex attribute on the tabbox. An apply attribute is used when you want to link the ZK UI to a GenericForwardComposer. The GenericForwardComposer, which acts as the controller in the MVC paradigm for ZK, will be discussed in detail in the next section.
The hflex attribute is used to lay out components horizontally. This is complemented by vflex which enables vertical layout control. Both hflex and vflex inform ZK how the component's parent should distribute the space among its children. In this case the author used true as the tabbox as the only child of the window. Setting hflex to true indicates that the component should fill the entire space available. Using hflex and vflex you can create complicated layouts efficiently. Looking into hflex and vflex in more detail is beyond the scope of this tutorial. For more information please refer to the ZK Developer's Reference guide.
Having implemented the skeleton view for main.zul, it is now necessary to move on to designing the department and employee view.
The authors had a decision to make when deciding how to implement the views. First of all the two views could be placed directly into main.zul, or they could be split up into separate files and included using the include component of ZK.
It was decided to separate the department and employee logic into separate files and include those files using ZK's include component. The reasons for this decision are as follows:
- Main.zul will be cleaner. Not having to place all the XML markup into the main.zul is much nicer for you when trying to understand the code, and makes each section more maintainable.
- It separates UI concerns from data binding. Separation into two zul files provides excellent separation of UI concerns. It also enables dynamic loading of each zul as covered in the following controller section.
The second reason will be discussed in detail later in this section of the tutorial. At the moment the tutorial's focus is centered on the individual zul files - departments.zul and employee.zul.
The Departments.zul is simple. It contains a listbox to show a list of departments. Underneath that is a groupbox with one textbox that represents the department name, as well as three buttons for triggering create, read, update, and delete (CRUD) operations.
Listing 9. Departments.zul
<?page title="new page title" contentType="text/html;charset=UTF-8"?> <div id="departmentdiv" hflex="true"> <listbox id="lstDepartment" multiple="false" rows="5"> <auxhead> <auxheader label="Departments" colspan="4" /> </auxhead> <listhead> <listheader label="ID" width="150px" /> <listheader label="Name" width="300px" /> </listhead> <listitem> <listcell label="" /> <listcell label="" /> </listitem> </listbox> <groupbox> <caption label="Department" /> Name: <textbox id="txtDepartmentName" cols="25" value="" /> <button id="btnAddDepartment" label="Add" width="36px" height="24px" /> <button id="btnUpdateDepartment" label="Update" width="46px" height="24px" /> <button id="btnDeleteDepartment" label="Delete" width="46px" height="24px" /> </groupbox> </div>
Listing 9 shows an extract of departments.zul without data binding,
which will be discussed in the controller section. Listing 9 should
not cause any confusion; attributes
label are the row of the attribute of
the listbox that dictates how many rows are visible. The multiple
attribute is a Boolean to specify whether or not selecting multiple
items is necessary.
Regarding components, a Listbox is used to display a number of items in a list, and supports the selecting of said items. The group box is used to visually group components together and give them a title (in this case referred to as a caption). The only components which may cause confusion are as follows:
- Auxhead/Auxheader: The control is used to display a header at the top of the list box. This can span as many columns as you require it to.
- Listheader: The list header dictates the headings of each listbox column. Notice that there are four columns, hence four list header elements.
- Listcell: Each listcell contains the information for each column. The number of listcells needs to match the number of list headers.
Figure 2 demonstrates the rendered output of Listing 9.
Figure 2. The rendered departments.zul
As demonstrated, ZK uses zul to provide developers and designers with a simple XML-based syntax similar to that of HTML.
The Employees.zul is very similar to departments.zul except for two
items: the intbox and the listbox shown in Listing 10. If you look
carefully at the listbox, you will notice that it has an attribute
called mold that is set as
A mold is a way of representing a control. Different molds can radically change the appearance of a component. A listbox can have two molds called default and select. The departments.zul demonstrated the default mold which looks and behaves in a similar fashion to a listbox appearing in Windows or Linux. However, a listbox in select mold behaves and looks like a combobox. For more information please refer to the ZK Component Reference.
Additionally, a keen observer will also notice the component intbox. An intbox is similar to a textbox, however, it only supports integers. If a string is entered then the validation of the box would fail.
Listing 10. Employee.zul
<?page title="new page title" contentType="text/html;charset=UTF-8"?> <div id="employeediv" hflex="true"> <listbox id="lstEmployee" multiple="false" rows="5"> <auxhead> <auxheader label="Employees" colspan="4" /> </auxhead> <listhead> <listheader label="ID" width="150px" /> <listheader label="First Name" width="300px" /> <listheader label="Last Name" width="300px" /> <listheader label="Age" width="150px" /> </listhead> <listitem> <listcell label="" /><listcell label="" /><listcell label="" /> <listcell label="" /> </listitem> </listbox> <groupbox> <caption label="Employee" /> First Name:<textbox id="txtFirstName" cols="25" value="" /> Last Name:<textbox id="txtLastName" cols="25" value="" /> Age:<intbox id="intAge" cols="1" value="" /> Department:<listbox id="lstDepartment" mold="select" model=""> <listitem /> </listbox> <button id="btnAddEmployee" label="Add" width="36px" height="24px" /> <button id="btnUpdateEmployee" label="Update" width="46px" height="24px" /> <button id="btnDeleteEmployee" label="Delete" width="46px" height="24px" /> </groupbox> </div>
Figure 3 shows the rendered result of employees.zul as included in Listing 10.
Figure 3. The rendered employees.zul
Having explored both the separated files, the tutorial now moves back to main.zul to discuss how you can include these separate files in other zul files.
ZK provides a special component named include. The include component is used to include output generated by another servlet. The servlet can be anything a JSF, JSP and even another ZUML page. In this application's case, another zul page needs to be included. The basic syntax of an include component is shown in Listing 11.
Listing 11. Include syntax
<include src="/module/departments.zul" />
As demonstrated, the attribute
src is used
to specify the file you wish to include.
There are two ways to include another ZUML document:
defer. By default it is set to auto,
meaning the real mode is decided automatically.
The auto mode (default) decides the mode based on the page that is to
be included. If the page ends with a zul or zhtml extension, then
instant mode is assumed. Otherwise, the
defer mode is assumed.
instant mode, the components defined in
the included page are instantiated instantly and added as children of
the include component. In the
the include component includes the page by going through the Servlet
container. Thus, it is okay to include any kind of pages, and is not
limited to ZUML documents.
defer mode means that an instance of
Page will be created in ZK. When a ZK request is asked to render a new
page, a new page will be created, and components that are created
during this request will all belong to this page. The author uses this
to the advantage of the application as it enables both departments.zul
and employee.zul to function as completely separate entities from
For use in this application, the include mode is set to
defer as shown in Listing 12.
Listing 12. Using defer
<include mode="defer" src="/module/departments.zul" />
You benefit from this when you want to reload the included zul files. This brings the tutorial nicely on to talk about controllers, which is the glue that holds the model and view together.