Creating a Simple Sightseeing Application"

From Documentation
 
(38 intermediate revisions by 6 users not shown)
Line 1: Line 1:
= Introduction =
+
=Before You Start=
  
This part aims to use a small sample application to demonstrate the strengths of ZK.
+
Translations are available in [[ZK_Getting_Started_fr/Creating_a_Simple_Sightseeing_Application|Français]] and [[ZK_Getting_Started_pt/Creating_a_Simple_Sightseeing_Application|Português]].
  
Our sample application is a sightseeing web site that uses Google Maps. Its web page has three parts:
+
'''Other Introductions'''
* Table(Implemented with Listbox): To show description for each place.
 
* Google Maps: Display real position of selected place.
 
* Detail pane: Detail information of selected place.
 
  
When user selects an item in the table, the location of that item will display on the Google Maps, and its coordinates will be shown on the bottom pane. The follow image is screenshot:
+
* [[ZK_Getting_Started/Learn_ZK_in_10_Minutes|Tutorial]] - A brief tutorial guides you through the most fundamental features and concepts of ZK.
 +
* [[ZK_Installation_Guide/Quick_Start/Create_and_Run_Your_First_ZK_Application_with_Eclipse_and_ZK_Studio|Creating Hello World with Eclipse and ZK Studio]] - Step by step to create a Web application from scratch with Eclipse and [http://www.zkoss.org/product/zkstudio.dsp ZK Studio].
 +
* [[ZK_Getting_Started/Creating_a_Database-driven_Application|Creating a database driven application]] - A tutorial exploring some of ZK's elements and how they work together to create a database-driven application
 +
* [[ZK Essentials]] - A book which walks you through the key concepts and features by building a working application from the ground up
  
[[File:Resort001.png]]
+
= Introduction =
  
We'll show two ways to build an Ajax-enabled web application using ZK: a basic way that does not use ZK's data binding features, and an advanced way that uses ZK's data binding features.
+
This tutorial aims to use a simple example to demonstrate how to implement a ZK application. You could [http://www.zkoss.org/resort try the application on line] first before keep reading.
  
You can [http://www.zkoss.org/resort try the application on line] if you cannot wait until finishing implementation.
+
Our sample application is a sightseeing web site that uses Google Maps. UI has three parts:
 +
* A list box: show every resort spots and allow the user to pick up for detailed information
 +
* Google Maps: display the location of the selected resort spot.
 +
* Detail pane: show detailed information of the selected resort spot.
  
=Before You Start=
+
[[File:Resort-s.jpg]]
  
Translations are available in [[ZK_Getting_Started_fr/Creating_a_Simple_Application|Français]] and [[ZK_Getting_Started_es/Creating_a_Simple_Application|Español]].
+
We'll show two ways to build an Ajax-enabled Web application using ZK: a straightforward way that manipulates data beans manually, and an automatic way by use of ZK data binding.
 
 
'''Other resources'''
 
 
 
* [[ZK_Getting_Started/Tutorial|Tutorial]] - A brief tutorial guides you through the most fundamental features and concepts of ZK.
 
* [[ZK_Installation_Guide/Quick_Start/Create_and_Run_Your_First_ZK_Application_with_Eclipse_and_ZK_Studio|Creating Hello World with Eclipse and ZK Studio]] - Step by step to create a Web application from scratch with Eclipse and [http://www.zkoss.org/product/zkstudio.dsp ZK Studio].
 
* [[ZK_Getting_Started/Creating_a_Database-driven_Application|Creating a database driven application]] - Step by step to create a database-driven application.
 
  
 
=Preparing=
 
=Preparing=
  
We can create a simple data model with Java class first because we will use this model latter -- no matter we use data binding or not --. The data model consists of the following attributes: name, description, latitude, and longitude.
+
We can create a simple data model with Java class first because we will use this model later. The data model consists of the following attributes: name, description, latitude, and longitude.
  
 
<source lang="java">
 
<source lang="java">
 
public class Resort {
 
public class Resort {
private String _name;
+
    private String _name;
private String _description;
+
    private String _description;
private Double _latitude;
+
    private double _latitude;
private Double _longitude;
+
    private double _longitude;
+
   
public Resort(){};
+
    public Resort() {
public Resort(String name, String description, Double latitude, Double longitude) {
+
    }
  _name = name;
+
 
  _description = description;
+
    public Resort(String name, String description, double latitude, double longitude) {
  _latitude = latitude;
+
        _name = name;
  _longitude = longitude;
+
        _description = description;
}
+
        _latitude = latitude;
// getter and setter methods are omitted.
+
        _longitude = longitude;
}
+
    }
</source>
+
 
 +
    // getter and setter methods are omitted.
 +
 
 +
    public static List<Resort> getAll() {
 +
      // Details are omitted.
 +
    }
 +
}
 +
</source>
  
=A Straightforward Way (Without Data Binding)=
+
=A Straightforward Way =
  
First, let's show a simple way to use and experience the strengths of ZK, without the trappings of ZK's details.
+
This section will introduce the first implementation. We call it the straightforward way since the application will manipulate the data model directly in Java. It is a common practice found in most frameworks. In the next section will introduce another implementation that use ZK data binding to manipulate the data model automatically.
  
 
==Design User Interface Page Using ZK Markup Language==
 
==Design User Interface Page Using ZK Markup Language==
  
We first develop the application's view page file: resort.zul; it includes a listbox (table), a gmaps(Google Maps), and a groupbox(pane).
+
We first develop the application's view page file: <code>resort.zul</code>. It includes three components: listbox, gmaps (Google Maps), and groupbox (detailed pane).
  
Notice how simple and clean resort.zul is -- no java codes or scriplets, all handler codes are defined in a separate Java file — ResortController.java.
+
To have better separation of UI and business logic, there is no Java code or scriplets in <code>resort.zul</code>. All business logic are defined in a separate Java file — <code>ResortController.java</code>.
  
The interaction between the zul file and the Java file is triggered by a user's activities. When a user selects an item in the listbox, the onSelect event of the listbox will be fired, and the refreshUI() method of ResortController.java will be invoked to display the selected item on the Google Maps, and to show the coordinates of selected item.
+
The interaction between the zul file and the Java file is triggered by a user's activities. When a user selects an item in the list box, an onSelect event will be fired, and the refreshUI() method of ResortController.java will be invoked to display the selected item on the Google Maps, and to show the coordinates of selected item.
  
 
<source lang="xml">
 
<source lang="xml">
 
<!-- resort.zul -->
 
<!-- resort.zul -->
<window id="win" use="org.zkforge.resort.ui.ResortController" title="ZK Tutorial" width="1024px" border="normal">
+
<?script content="zk.googleAPIkey='ABQIAAAAmGxmYR57XDAbAumS9tV5fxQXyylOlR69a1vFTcUcpV6DXdesOBSMEHfkewcSzwEwBT7UzVx8ep8vjA'"?>
<script src="http://maps.google.com/maps?file=api&v=2&key=ABQIAAAACZ90QS5pNiEvbXhI0k2NLRTGXUEQDrMr1bP0DVG
+
 
8X36ZVCheaRQMK05Rsdneh4skNF6KXaLI8maLlA" type="text/javascript"/>
+
<window id="win" title="ZK Tutorial" border="normal"
<hbox>
+
apply="org.zkforge.resort.ui.ResortController" width="1024px">
<listbox id="lb" onSelect="win.refreshUI()">
+
<hbox>
  <listhead sizable="true">
+
<listbox id="lb" hflex="1">
  <listheader label="Name" width="100px"/>
+
<listhead sizable="true">
  <listheader label="Description" width="250px"/>  
+
<listheader label="Name" width="100px"/>
  </listhead>
+
<listheader label="Description" width="285px"/>
  <listitem forEach="${win.resorts}" value="${each}">
+
</listhead>
  <listcell label="${each.name}" />
+
</listbox>
  <listcell label="${each.description}" /> 
+
<gmaps id="gmap" zoom="16" showTypeCtrl="true" mapType="satellite" showLargeCtrl="true" width="610px" height="400px">
  </listitem>
+
<ginfo id="ginfo"/>
</listbox>
+
</gmaps>
<gmaps id="gmap" zoom="16" showTypeCtrl="true" mapType="satellite" showLargeCtrl="true" width="610px"  
+
</hbox>
height="400px">
+
<groupbox id="gb" mold="3d" width="100%">
  <ginfo id="ginfo"/>
+
<caption label="Resort"/>
</gmaps>
+
Name:<textbox readonly="true" id="name"/>
</hbox>
+
Description:<textbox readonly="true" id="desc"/>
<groupbox mold="3d" width="100%">
+
Longitude:<doublebox readonly="true" id="longtitude"/>
  <caption label="Resort"/>
+
Latitude:<doublebox readonly="true" id="latitude"/>
  Name:       <textbox id="name" disabled="true"/>
+
</groupbox>
  Description:<textbox id="desc" disabled="true"/>  
 
  Latitude:   <doublebox id="lat" disabled="true"/>
 
  Longitude: <doublebox id="lng" disabled="true"/>
 
</groupbox>  
 
 
</window>
 
</window>
 
</source>
 
</source>
Line 93: Line 93:
 
==Manipulate UI Components Using Java==
 
==Manipulate UI Components Using Java==
  
In the Java file(ResortController.java), we retrieve the UI components by their id, and put the data of the selected item into them. Then, ZK engines will update the web page in Ajax automatically.
+
In the Java file(ResortController.java), we retrieve the UI components by their id, and put the data of the selected item into them. Then, ZK engines will update the web page in Ajax automatically. Furthermore, we could allow users to modify the data bean without adding a single line of Java code.
  
<source lang="xml">
+
<source lang="java">
<!--ResortController.java -->
+
// ResortController.java
public class ResortController extends Window {  
+
public class ResortController extends GenericForwardComposer {
List _resorts = new ArrayList();
+
 
 
+
    private static final long serialVersionUID = -4023064279380075239L;
public ResortController(){
+
    private Listbox lb;
  _resorts.add(new Resort("La Tour Eiffel",
+
    private Gmaps gmap;
    "Insolite ! Découvrez la Tour Eiffel autrement.",48.8585599391,2.2945332527));
+
    private Ginfo ginfo;
  _resorts.add(new Resort("Buckingham Palace",
+
    private Textbox name;
    "The official London residence of the sovereign.",51.5013698182,-0.1416689157));
+
    private Textbox desc;
  _resorts.add(new Resort("東京タワ",
+
    private Doublebox latitude;
    "総數4萬の光ファンタジーと都內最大級15mのツリー!",35.6583487578,139.7457217178));
+
    private Doublebox longtitude;
  _resorts.add(new Resort("Der Kölner Dom",
+
 
    "Offizieller Name Hohe Domkirche St. Peter und Maria",50.9414206771,6.9586372375));
+
    public void doAfterCompose(Component comp) throws Exception {
}
+
        super.doAfterCompose(comp);
 
+
       
public void refreshUI(){
+
        lb.setItemRenderer(new ListitemRenderer() {
  Listbox lb = (Listbox) getFellow("lb");
+
            public void render(Listitem item, Object data) throws Exception {
  Resort resort = (Resort) lb.getSelectedItem().getValue();
+
                Resort value = (Resort)data;
  ((Textbox)getFellow("name")).setValue(resort.getName());
+
                item.appendChild(new Listcell(value.getName()));
  ((Textbox)getFellow("desc")).setValue(resort.getName());
+
                item.appendChild(new Listcell(value.getDescription()));
  ((Doublebox)getFellow("lat")).setValue(resort.getLatitude());
+
                item.setValue(value);
  ((Doublebox)getFellow("lng")).setValue(resort.getLongitude());
+
            }
 
+
        });
  Gmaps gmap = (Gmaps) getFellow("gmap");
+
       
  Ginfo ginfo = (Ginfo) getFellow("ginfo");
+
        lb.setModel(new ListModelList(Resort.getAll()));
  ginfo.setLat(resort.getLatitude());
+
    }
  ginfo.setLng(resort.getLongitude());
+
   
  ginfo.setContent(resort.getDescription());
+
    public void onSelect$lb() {
  gmap.panTo(resort.getLatitude(),resort.getLongitude());
+
        refreshUI();
  gmap.setZoom(16);
+
    }
  gmap.openInfo(ginfo);
+
 
}
+
    private void refreshUI() {
public List getResorts() {
+
        Resort resort = (Resort) lb.getSelectedItem().getValue();
  return _resorts;
+
        double latitudeValue = resort.getLatitude().doubleValue();
}
+
        double longtitudeValue = resort.getLongitude().doubleValue();
public void setResorts(List resorts) {
+
       
  _resorts = resorts;
+
        name.setValue(resort.getName());
}
+
        desc.setValue(resort.getName());
 +
        latitude.setValue(resort.getLatitude());
 +
        longtitude.setValue(resort.getLongitude());
 +
        ginfo.setLat(latitudeValue);
 +
        ginfo.setLng(longtitudeValue);
 +
        ginfo.setContent(resort.getDescription());
 +
        gmap.panTo(latitudeValue, longtitudeValue);
 +
        gmap.setZoom(16);
 +
        gmap.openInfo(ginfo);
 +
    }
 
}
 
}
 
</source>
 
</source>
Line 147: Line 156:
 
One simple way is to directly define such relations in the web page. One of the major differences is that we add another data bean which represents the selected item, and then bind all of related ZK components to it.
 
One simple way is to directly define such relations in the web page. One of the major differences is that we add another data bean which represents the selected item, and then bind all of related ZK components to it.
  
<source lang="java">
+
<source lang="xml">
    <!-- resort_databind.zul -->
+
<!-- resort_databind.zul -->
    <?init class="org.zkoss.zkplus.databind.AnnotateDataBinderInit" ?>
+
<?init class="org.zkoss.zkplus.databind.AnnotateDataBinderInit" ?>
    <window id="win" use="org.zkforge.resort.ui.ResortController2" title="ZK Tutorial" width="1024px" border="normal">
+
<?script content="zk.googleAPIkey='ABQIAAAAmGxmYR57XDAbAumS9tV5fxQXyylOlR69a1vFTcUcpV6DXdesOBSMEHfkewcSzwEwBT7UzVx8ep8vjA'" ?>
    <script src="http://maps.google.com/maps?file=api&v=2&key=ABQIAAAACZ90QS5pNiEvbXhI0k2NLRTGXUEQDrMr1bP0DVG
+
 
    8X36ZVCheaRQMK05Rsdneh4skNF6KXaLI8maLlA"  type="text/javascript"/>
+
<window id="win" apply="org.zkforge.resort.ui.ResortController2" title="ZK Tutorial" width="1024px" border="normal">
    <hbox>
+
<hbox>
    <listbox model="@{win.resorts}" selectedItem="@{win.selected}" onSelect="win.refreshUI()">
+
<listbox id="lb" model="@{win$ResortController2.resorts}" selectedItem="@{win$ResortController2.selected}">
      <listhead sizable="true">
+
<listhead sizable="true">
      <listheader label="Name" width="100px"/>
+
<listheader label="Name" width="100px"/>
      <listheader label="Description" width="250px"/>  
+
<listheader label="Description" width="285px"/>
      </listhead>
+
</listhead>
      <listitem self="@{each=resort}">
+
<listitem self="@{each=resort}">
      <listcell label="@{resort.name}" />
+
<listcell label="@{resort.name}" />
      <listcell label="@{resort.description}" />  
+
<listcell label="@{resort.description}" />
      </listitem>
+
</listitem>
    </listbox>  
+
</listbox>
    <gmaps id="gmap" zoom="16" showTypeCtrl="true" mapType="satellite" showLargeCtrl="true" width="610px"  
+
<gmaps id="gmap" zoom="16" showTypeCtrl="true" mapType="satellite" showLargeCtrl="true" width="610px" height="400px">
      height="400px">
+
<ginfo id="ginfo" />
      <ginfo id="ginfo" lng="@{win.selected.longitude}" lat="@{win.selected.latitude}"
+
</gmaps>
      content="@{win.selected.description}"/>
+
</hbox>
    </gmaps>
+
<groupbox id="gb" mold="3d" width="100%">
    </hbox>
+
<caption label="Resort"/>
    <groupbox id="gb" mold="3d" width="100%">
+
Name:<textbox id="name" value="@{win$ResortController2.selected.name}" readonly="true"/>
      <caption label="Resort"/>
+
Description:<textbox  id="desc" value="@{win$ResortController2.selected.description}" readonly="true"/>
      Name:<textbox id="name" value="@{win.selected.name}" disabled="true"/>
+
Longitude:<doublebox id="lng" value="@{win$ResortController2.selected.longitude}" readonly="true"/>
      Description:<textbox  id="desc" value="@{win.selected.description}" disabled="true"/>  
+
Latitude:<doublebox id="lat" value="@{win$ResortController2.selected.latitude}" readonly="true"/>
      Latitude:<doublebox id="lat" value="@{win.selected.latitude}" disabled="true"/>
+
</groupbox>
      Longitude:<doublebox id="lng" value="@{win.selected.longitude}" disabled="true"/>
+
</window>
    </groupbox>
 
    </window>
 
 
</source>
 
</source>
  
Line 185: Line 192:
  
 
<source lang="java">
 
<source lang="java">
    <!--ResortController2.java -->
+
// ResortController2.java
   
+
public class ResortController2 extends GenericForwardComposer {
    public class ResortController extends Window {  
+
 
    List _resorts = new ArrayList();
+
    private static final long serialVersionUID = -7504093487870918898L;
    Resort _selected = new Resort();
+
    private List<Resort> _resorts;
   
+
    private Resort _selected;
    public ResortController(){
+
    private Gmaps gmap;
      _resorts.add(new Resort("La Tour Eiffel",
+
    private Ginfo ginfo;
        "Insolite ! Découvrez la Tour Eiffel autrement.",48.8585599391,2.2945332527));
+
 
      _resorts.add(new Resort("Buckingham Palace",
+
    public void doAfterCompose(Component comp) throws Exception {
        "The official London residence of the sovereign.",51.5013698182,-0.1416689157));
+
        super.doAfterCompose(comp);
      _resorts.add(new Resort("東京タワ",
+
        setResorts(Resort.getAll());
        "総數4萬の光ファンタジーと都內最大級15mのツリー!",35.6583487578,139.7457217178));
+
        _selected = new Resort();
      _resorts.add(new Resort("Der Kölner Dom",
 
        "Offizieller Name Hohe Domkirche St. Peter und Maria",50.9414206771,6.9586372375));
 
    }
 
     
 
    public void refreshUI(){
 
      Gmaps gmap = (Gmaps) getFellow("gmap");
 
      Ginfo ginfo = (Ginfo) getFellow("ginfo"); 
 
      gmap.panTo(ginfo.getLat(),ginfo.getLng());
 
      gmap.setZoom(16);
 
      gmap.openInfo(ginfo);
 
    }
 
    public List getResorts() {
 
      return _resorts;
 
    }
 
    public void setResorts(List resorts) {
 
      _resorts = resorts;
 
    }
 
    public Resort getSelected() {
 
      return _selected;
 
    }
 
    public void setSelected(Resort selected) {
 
      _selected = selected;
 
    }
 
 
     }
 
     }
 +
   
 +
    public void onSelect$lb() {
 +
        refreshUI();
 +
    }
 +
 +
    private void refreshUI() {
 +
        double latitude = _selected.getLatitude().doubleValue();
 +
        double longtitude = _selected.getLongitude().doubleValue();
 +
       
 +
        ginfo.setLat(latitude);
 +
        ginfo.setLng(longtitude);
 +
        ginfo.setContent(_selected.getDescription());
 +
        gmap.panTo(latitude, longtitude);
 +
        gmap.setZoom(16);
 +
        gmap.openInfo(ginfo);
 +
    }
 +
 +
    public Resort getSelected() {
 +
        return _selected;
 +
    }
 +
 +
    public void setSelected(Resort selected) {
 +
        _selected = selected;
 +
    }
 +
 +
    public void setResorts(List<Resort> _resorts) {
 +
        this._resorts = _resorts;
 +
    }
 +
 +
    public List<Resort> getResorts() {
 +
        return _resorts;
 +
    }
 +
}
 
</source>
 
</source>
  
Line 227: Line 244:
  
 
#Install Java SDK
 
#Install Java SDK
#:If you haven't already done so, please download and install the Java SDK SUN Java Standard SDK.
+
#:If you haven't already done so, please download and install [http://java.sun.com/javase/downloads/index.jsp Java SDK].
 
#Install a Servlet Container
 
#Install a Servlet Container
#:If you don't already have a Servlet container, please download and install Apache Tomcat.
+
#:If you don't already have a Servlet container, please download and install [http://tomcat.apache.org/download-55.cgi Apache Tomcat].
 
#Download the Web Application
 
#Download the Web Application
#:Download this application's files here.
+
#:Download this application's files [http://sourceforge.net/projects/zkforge/files/ZK%20Resort/resort-0.8.1.zip/download here].
 
#Unzip the file
 
#Unzip the file
 
#:Unzip resort.zip, and copy resort.war to $TOMCAT_HOME/webapps/.
 
#:Unzip resort.zip, and copy resort.war to $TOMCAT_HOME/webapps/.
Line 237: Line 254:
  
 
----
 
----
Last Update : {{REVISIONYEAR}}/{{REVISIONMONTH}}/{{REVISIONDAY}}
+
{{LastUpdated}}

Latest revision as of 08:43, 24 July 2012

Before You Start

Translations are available in Français and Português.

Other Introductions

Introduction

This tutorial aims to use a simple example to demonstrate how to implement a ZK application. You could try the application on line first before keep reading.

Our sample application is a sightseeing web site that uses Google Maps. UI has three parts:

  • A list box: show every resort spots and allow the user to pick up for detailed information
  • Google Maps: display the location of the selected resort spot.
  • Detail pane: show detailed information of the selected resort spot.

Resort-s.jpg

We'll show two ways to build an Ajax-enabled Web application using ZK: a straightforward way that manipulates data beans manually, and an automatic way by use of ZK data binding.

Preparing

We can create a simple data model with Java class first because we will use this model later. The data model consists of the following attributes: name, description, latitude, and longitude.

public class Resort {
    private String _name;
    private String _description;
    private double _latitude;
    private double _longitude;
    
    public Resort() {
    }

    public Resort(String name, String description, double latitude, double longitude) {
        _name = name;
        _description = description;
        _latitude = latitude;
        _longitude = longitude;
    }

    // getter and setter methods are omitted.

    public static List<Resort> getAll() {
       // Details are omitted.
    }
}

A Straightforward Way

This section will introduce the first implementation. We call it the straightforward way since the application will manipulate the data model directly in Java. It is a common practice found in most frameworks. In the next section will introduce another implementation that use ZK data binding to manipulate the data model automatically.

Design User Interface Page Using ZK Markup Language

We first develop the application's view page file: resort.zul. It includes three components: listbox, gmaps (Google Maps), and groupbox (detailed pane).

To have better separation of UI and business logic, there is no Java code or scriplets in resort.zul. All business logic are defined in a separate Java file — ResortController.java.

The interaction between the zul file and the Java file is triggered by a user's activities. When a user selects an item in the list box, an onSelect event will be fired, and the refreshUI() method of ResortController.java will be invoked to display the selected item on the Google Maps, and to show the coordinates of selected item.

<!-- resort.zul -->
<?script content="zk.googleAPIkey='ABQIAAAAmGxmYR57XDAbAumS9tV5fxQXyylOlR69a1vFTcUcpV6DXdesOBSMEHfkewcSzwEwBT7UzVx8ep8vjA'"?>

<window id="win" title="ZK Tutorial" border="normal"
 apply="org.zkforge.resort.ui.ResortController" width="1024px">
	<hbox>
		<listbox id="lb" hflex="1">
			<listhead sizable="true">
				<listheader label="Name" width="100px"/>
				<listheader label="Description" width="285px"/>
			</listhead>
		</listbox>	
		<gmaps id="gmap" zoom="16" showTypeCtrl="true" mapType="satellite" showLargeCtrl="true" width="610px" height="400px">
			<ginfo id="ginfo"/>
		</gmaps>
	</hbox>
	<groupbox id="gb" mold="3d" width="100%">
		<caption label="Resort"/>
		Name:<textbox readonly="true" id="name"/>
		Description:<textbox readonly="true" id="desc"/>
		Longitude:<doublebox readonly="true" id="longtitude"/>
		Latitude:<doublebox readonly="true" id="latitude"/>
	</groupbox>
</window>

Manipulate UI Components Using Java

In the Java file(ResortController.java), we retrieve the UI components by their id, and put the data of the selected item into them. Then, ZK engines will update the web page in Ajax automatically. Furthermore, we could allow users to modify the data bean without adding a single line of Java code.

// ResortController.java
public class ResortController extends GenericForwardComposer {

    private static final long serialVersionUID = -4023064279380075239L;
    private Listbox lb;
    private Gmaps gmap;
    private Ginfo ginfo;
    private Textbox name;
    private Textbox desc;
    private Doublebox latitude;
    private Doublebox longtitude;

    public void doAfterCompose(Component comp) throws Exception {
        super.doAfterCompose(comp);
        
        lb.setItemRenderer(new ListitemRenderer() {
            public void render(Listitem item, Object data) throws Exception {
                Resort value = (Resort)data;
                item.appendChild(new Listcell(value.getName()));
                item.appendChild(new Listcell(value.getDescription()));
                item.setValue(value);
            }
        });
        
        lb.setModel(new ListModelList(Resort.getAll()));
    }
    
    public void onSelect$lb() {
        refreshUI();
    }

    private void refreshUI() {
        Resort resort = (Resort) lb.getSelectedItem().getValue();
        double latitudeValue = resort.getLatitude().doubleValue();
        double longtitudeValue = resort.getLongitude().doubleValue();
        
        name.setValue(resort.getName());
        desc.setValue(resort.getName());
        latitude.setValue(resort.getLatitude());
        longtitude.setValue(resort.getLongitude());
        ginfo.setLat(latitudeValue);
        ginfo.setLng(longtitudeValue);
        ginfo.setContent(resort.getDescription());
        gmap.panTo(latitudeValue, longtitudeValue);
        gmap.setZoom(16);
        gmap.openInfo(ginfo);
    }
}

This example illustrates the simplicity of building an Ajax-enabled web application with ZK. The "View" and "Controller" are cleanly separated, and no JavaScript code is required! We believe that the best way to use Ajax is to not have to know of its existence.

An Automatic Way (With Data Binding)

To simplify the job of maintaining the consistency of data between the data bean and the user interface, ZK provides the mechanism of data-binding. You simply define the relations between the "Model" (data beans) and the "View" (UI components), and ZK's data-binding feature will maintain the data consistency between them automatically.

Define Relations between Data Bean and UI Components

One simple way is to directly define such relations in the web page. One of the major differences is that we add another data bean which represents the selected item, and then bind all of related ZK components to it.

<!-- resort_databind.zul -->
<?init class="org.zkoss.zkplus.databind.AnnotateDataBinderInit" ?>
<?script content="zk.googleAPIkey='ABQIAAAAmGxmYR57XDAbAumS9tV5fxQXyylOlR69a1vFTcUcpV6DXdesOBSMEHfkewcSzwEwBT7UzVx8ep8vjA'" ?>

<window id="win" apply="org.zkforge.resort.ui.ResortController2" title="ZK Tutorial" width="1024px" border="normal">
	<hbox>
	<listbox id="lb" model="@{win$ResortController2.resorts}" selectedItem="@{win$ResortController2.selected}">
		<listhead sizable="true">
			<listheader label="Name" width="100px"/>
			<listheader label="Description" width="285px"/>			
		</listhead>
		<listitem self="@{each=resort}">
			<listcell label="@{resort.name}" />
			<listcell label="@{resort.description}" />			
		</listitem>
	</listbox>	
	<gmaps id="gmap" zoom="16" showTypeCtrl="true" mapType="satellite" showLargeCtrl="true" width="610px" height="400px">
		<ginfo id="ginfo" />
	</gmaps>
	</hbox>
	<groupbox id="gb" mold="3d" width="100%">
		<caption label="Resort"/>
		Name:<textbox id="name" value="@{win$ResortController2.selected.name}" readonly="true"/>
		Description:<textbox  id="desc" value="@{win$ResortController2.selected.description}" readonly="true"/>
		Longitude:<doublebox id="lng" value="@{win$ResortController2.selected.longitude}" readonly="true"/>
		Latitude:<doublebox id="lat" value="@{win$ResortController2.selected.latitude}" readonly="true"/>	
	</groupbox>
</window>

Revise the Java File

With the help of data-binding, the handling codes in ResortController.java are much reduced. Once the user selects a different item, the data bean will be changed, and then data of all related ZK components will be updated automatically.

// ResortController2.java
public class ResortController2 extends GenericForwardComposer {

    private static final long serialVersionUID = -7504093487870918898L;
    private List<Resort> _resorts;
    private Resort _selected;
    private Gmaps gmap;
    private Ginfo ginfo;

    public void doAfterCompose(Component comp) throws Exception {
        super.doAfterCompose(comp);
        setResorts(Resort.getAll());
        _selected = new Resort();
    }
    
    public void onSelect$lb() {
        refreshUI();
    }

    private void refreshUI() {
        double latitude = _selected.getLatitude().doubleValue();
        double longtitude = _selected.getLongitude().doubleValue();
        
        ginfo.setLat(latitude);
        ginfo.setLng(longtitude);
        ginfo.setContent(_selected.getDescription());
        gmap.panTo(latitude, longtitude);
        gmap.setZoom(16);
        gmap.openInfo(ginfo);
    }

    public Resort getSelected() {
        return _selected;
    }

    public void setSelected(Resort selected) {
        _selected = selected;
    }

    public void setResorts(List<Resort> _resorts) {
        this._resorts = _resorts;
    }

    public List<Resort> getResorts() {
        return _resorts;
    }
}

Installing the Web Application

  1. Install Java SDK
    If you haven't already done so, please download and install Java SDK.
  2. Install a Servlet Container
    If you don't already have a Servlet container, please download and install Apache Tomcat.
  3. Download the Web Application
    Download this application's files here.
  4. Unzip the file
    Unzip resort.zip, and copy resort.war to $TOMCAT_HOME/webapps/.
  5. Start your Web Server, and point your browser to: http://localhost:8080/resort/resort.zul

Last Update : 2012/07/24