Ajax GSP with ZK"

From Documentation
m (correct highlight (via JWB))
 
(27 intermediate revisions by 2 users not shown)
Line 1: Line 1:
 
{{Template:Smalltalk_Author|
 
{{Template:Smalltalk_Author|
 
|author=Hawk Chen, Engineer, Potix Corporation
 
|author=Hawk Chen, Engineer, Potix Corporation
|date=December 20, 2011
+
|date=January 16, 2012
 
|version=ZK 5
 
|version=ZK 5
 
}}
 
}}
Line 8: Line 8:
  
 
Grails is an open-source web application framework based on the Groovy language. Not just purely a framework, Grails also provides a highly productive development mode including web server, automatic reload of resources and seamless integration with two other best practices, Spring and Hibernate.
 
Grails is an open-source web application framework based on the Groovy language. Not just purely a framework, Grails also provides a highly productive development mode including web server, automatic reload of resources and seamless integration with two other best practices, Spring and Hibernate.
Groovy Server Pages (GSP), which is an evolution from Java Server Pages (JSP) is Grails’ primary view technology.  
+
Grails Server Pages (GSP), which is an evolution from Java Server Pages (JSP) is Grails’ primary view technology.  
  
Compared to JSP, GSP helps simplify implementation procedures and usage of custom tag libraries. It uses SiteMesh application framework for page decoration.Please note that only some JavaScript libraries (Prototype and Scriptaculous) can be supported out of the box when utilizing Ajax with GSP. Therefore, developers may have to deal with tedious Ajax details and various JavaScript API integration issues and this is why ZK comes in handy. With the use of a Grails plugin - zkui, developers now empower their level of GSP usage with Ajax by embedding ZK UI components.
+
Compared to JSP, GSP helps simplify implementation procedures and usage of custom tag libraries. It uses "''SiteMesh''" application framework for page decoration.Please note that only some JavaScript libraries (Prototype and Scriptaculous) can be supported out of the box when utilizing Ajax with GSP. Therefore, developers may have to deal with tedious Ajax details and various JavaScript API integration issues and this is why ZK comes in handy. With the use of a Grails plugin - ''zkui'', developers now empower their level of GSP usage with Ajax by embedding ZK UI components.
  
 
This article will demonstrate how ZK can enhance the interactivity of GSP with Ajax.  To get a better understanding of this article, it is recommended for readers to know the basic concept of Grails, such as domain class, controller, GSP, and Groovy. The development environment is under Eclipse 3.6, SpringSource Tool Suite 2.7.1., Grails Support 2.7.1., Grails 1.3.7., Groovy-Eclipse Plugin 2.5.1 and zkui 0.3.2.
 
This article will demonstrate how ZK can enhance the interactivity of GSP with Ajax.  To get a better understanding of this article, it is recommended for readers to know the basic concept of Grails, such as domain class, controller, GSP, and Groovy. The development environment is under Eclipse 3.6, SpringSource Tool Suite 2.7.1., Grails Support 2.7.1., Grails 1.3.7., Groovy-Eclipse Plugin 2.5.1 and zkui 0.3.2.
Line 31: Line 31:
 
===Application Example Background===
 
===Application Example Background===
  
We are going to build a simple web application called RaceTrack. RaceTrack is designed for a running club which holds several races. The purpose of this is to show how users of the running club can easily manage their held races through creating, updating and deleting records.
+
We are going to build a simple web application called "''RaceTrack''". "''RaceTrack''" is designed for a running club which holds several races. The purpose of this example is to show how users of the running club can easily manage their held races through creating, updating and deleting records.
  
 
===Create a Project===
 
===Create a Project===
  
To create a project “racetrack”, use eclipse File\New\Grails Project or SpringSource Tool Suite\Create\Grails Project.
+
To create the "''RaceTrack''" project , use eclipse File\New\Grails Project or SpringSource Tool Suite\Create\Grails Project.
You must install plugin “zkui” for harnessing the power of ZK components.  
+
You must install the ''zkui'' plugin in order to harness the power of ZK components.  
  
Right click the RaceTrack project in Eclipse and hover to Grails Tools. To install the plugin zkui, type “install-plugin zkui” at the Grails Command Prompt window or search it with the Grails Plugin Manager.
+
Right click the "''RaceTrack''" project in Eclipse and hover to Grails Tools. To install the ''zkui'' plugin, type “install-plugin zkui” at the Grails Command Prompt window or search it with the Grails Plugin Manager.
  
 
[[File:installation_msg.png|thumb|600px|none]]
 
[[File:installation_msg.png|thumb|600px|none]]
Line 68: Line 68:
 
===Static Scaffolding===
 
===Static Scaffolding===
  
With zkui static scaffolding, we can complete the four basic functions: Create, Read, Update and Delete (CRUD) without writing any code. Type “zkui-generate-all racetrack.Race” at the Grails Command Prompt window and zkui will generate 3 GSP, 1 controller, and 3 composers (under grails-app\composers). To render ZK components in a GSP, you still need to add <z:resources/> in the <head> of grails-app\views\layouts\main.gsp.
+
With ''zkui'' static scaffolding, we can complete the four basic functions: Create, Read, Update and Delete (CRUD) without writing any code. Type "''zkui-generate-all racetrack.Race''" at the Grails Command Prompt window and ''zkui'' will generate 3 GSPs, 1 controller, and 3 composers (under grails-app\composers). To render ZK components in a GSP, you need to add <code><z:resources/></code> in the <code><head></code> of grails-app\views\layouts\main.gsp.
  
 
[[File:static_scaffolding.png|none]]
 
[[File:static_scaffolding.png|none]]
  
Let’s take a closer look at these generated artifacts. The controller class has no big difference with the original Grails controller. But GSP is filled with tags with a prefix “z”. Those tags represent the ZK UI components. The tag name is the component’s name. ZK provides more than 200 components and zkui supports most of them [1]. Each GSP has a <z:window> to enclose all ZK components, and the window’s attribute “apply” specifies which composers to handle their events.
+
Let’s take a closer look at these generated artifacts. The controller class has no big difference with the original Grails controller,but GSP is filled with tags with a prefix “z”. Those tags represent the ZK UI components. The tag name is the component’s name. ZK provides more than 200 components and ''zkui'' supports most of them <ref>Grails ZK UI Plugin - Reference Documentation http://xiaochong.github.com/zkui/manual/index.html </ref> Each GSP has a <code><z:window></code> to enclose all ZK components, and the window’s attribute “apply” specifies which composers to handle their events.
  
 
<source lang="xml">  
 
<source lang="xml">  
Line 80: Line 80:
 
</source>  
 
</source>  
  
Hence in list.gsp, the ListComposer will handle events from all components inside <z:window> including the window itself.
+
Hence in <b>list.gsp</b>, the <code>ListComposer</code> will handle events from all components inside <code><z:window></code> including the window itself.
  
Now run the application and visit the page via the link http://localhost:8080/racetrack/race/create, after that you will see a form composed by ZK components corresponding to each Race class’ property. We fill out the form partially and then click the “Create” button. Then we can see the validation message pop-up instantly without reloading the page. Now this GSP is powered by Ajax.
+
Now, run the application and visit the page via the link http://localhost:8080/racetrack/race/create, you will see a form composed by ZK components corresponding to each Race class’ property. We fill out the form partially and then click the “Create” button. Then we can see the validation message pop-up instantly without reloading the page. Now, this GSP is powered by Ajax.
  
 
[[File:validation_msg.png|thumb|400px|none]]
 
[[File:validation_msg.png|thumb|400px|none]]
  
Among all the generated artifacts, the composers under grails-app\composers are unfamiliar to Grails developers. This term “composer” comes from ZK. It plays the same role as the Grails controller in a MVC pattern, but the difference is that the Grails controller handles requests from GSP while the composer only handle events issued from the ZK components. Another notable difference is that the composer can manipulate ZK components on GSP in which we’ll talk about in the next section.
+
Among all the generated artifacts, the composers under grails-app\composers are unfamiliar to Grails developers. This term “composer” comes from ZK. It plays the same role as the Grails controller in a MVC pattern, with a difference in which Grails controller handles requests from GSP while the composer of ZK only handles events issued from ZK components. Another notable difference is that the composer can manipulate ZK components on GSP which we will talk about in the next section.
  
 
===Composer in Depth===
 
===Composer in Depth===
  
There are 3 composers, and each of them corresponds to one GSP which can be easily identified by its naming. Open the ListComposer.groovy which handles the event from list.gsp. Let’s first look at these variables.
+
There are 3 composers, and each of them corresponds to one GSP which can be easily identified by its naming. Open <code>ListComposer.groovy</code> which handles events from <b>list.gsp</b>. Let’s first look at these variables.
  
<tt>
+
'''ListComposer.groovy'''
 
+
<source lang="groovy">
    Grid grid
+
Grid grid
    Paging paging
+
Paging paging
    Longbox idLongbox
+
Longbox idLongbox
 +
</source>
  
</tt>  
+
It seems normal, but you’ll find that there are three ZK components whose variable names are identical to that of ZK component tag’s ''id'' attribute in <b>list.gsp</b>. This is not a coincidence, it is a feature of the composer called component Auto-wiring. It is automatically enabled by mapping a naming convention and a variable type. Each ZK component has a corresponding class (ex: <z:grid> is org.zkoss.zul.Grid), and if you put the correct name and type in the composer upon your component tag, the ''zkui'' plugin will wire components for you. Through these variables we can manipulate ZK components in a composer. In fact, static scaffolding has already done it for you.
  
It seems normal as usual, but you’ll find that there are three ZK components whose variable names are identical to that of ZK component tag’s attribute “id” in list.gsp. This is not a coincidence, it is a feature of the composer called component Auto-wiring. It is automatically enabled by mapping a naming convention and a variable type. Each ZK component has a corresponding class (ex: <z:grid> is org.zkoss.zul.Grid), and if you put the correct name and type in the composer upon your component tag, the zkui plugin will wire components for you. Through these variables we can manipulate ZK components in a composer. In fact, static scaffolding has already done it for you.
+
You can see a closure ''afterComposer''. This closure is called when all ZK components and its descendants are instantiated and rendered. So we usually do some post-processing to components in it.
  
You can see a closure “afterComposer”. This closure is called when all ZK components and its descendants are instantiated and rendered. So we usually do some post-processing to components in it.
 
  
<source lang="java">  
+
'''ListComposer.groovy'''
 +
<source lang="groovy">  
  
 
def afterCompose = {Component comp ->
 
def afterCompose = {Component comp ->
Line 114: Line 115:
 
</source>  
 
</source>  
  
<li>Line 2 sets a custom row renderer to grid component and this means that we can draw each row by ourselves.  
+
* Line 2 sets a custom row renderer to grid component and this means that we can draw each row by ourselves.  
<li>Line 3 attaches a data source that will be used in the renderer. Then, we look inside the redraw() method:
+
*Line 3 attaches a data source that will be used in the renderer.  
 +
 
 +
 
 +
 
 +
Then, we look inside the <code>redraw()</code> method:
  
<source lang="java">  
+
'''ListComposer.groovy'''
 +
<source lang="groovy">  
  
 
     private redraw(int activePage = 0) {
 
     private redraw(int activePage = 0) {
Line 135: Line 141:
 
</source>  
 
</source>  
  
<li>Line 4 constructs a race list upon search criteria. The only criterion is the race id we can retrieve by the ZK component. By the use of “idLongbox.value”, we can get the user inputted id in the textbox.  
+
* Line 4 constructs a race list upon search criteria. The only criterion is the race ''id'' which we can retrieve from the ZK component by the use of ''idLongbox.value'', we can get the user's inputted ''id'' in the textbox.
 +
* Line 12 changes the Grid’s data source and will cause the grid to re-render.
  
<li>Line 12 changes the Grid’s data source and will cause the grid to re-render.
 
  
<source lang="java">  
+
'''ListComposer.groovy'''
 +
<source lang="groovy">  
  
 
     private rowRenderer = {Row row, Object id ->
 
     private rowRenderer = {Row row, Object id ->
Line 162: Line 169:
 
</source>  
 
</source>  
  
We use rowRenderer to customize Grid’s rendering. For example, to create a ZK component dynamically, zkui provides a leftshift (<<) operator to append a child to each row. The id comes from the grid’s data source. According to the code after line 3, you can see it adds a link, 4 labels, and 2 tool bar buttons (update, delete) in a row.
+
We use <code>rowRenderer</code> to customize Grid’s rendering. For example, to create a ZK component dynamically, ''zkui'' provides a leftshift (<<) operator to append a child to each row. The ''id'' comes from the grid’s data source. According to the code after line 3, you can see how it adds a link, 4 labels, and 2 tool bar buttons (update, delete) in a row.
  
 
[[File:customise_grid.png|thumb|500px|none]]
 
[[File:customise_grid.png|thumb|500px|none]]
Line 168: Line 175:
 
===Instant Deletion===  
 
===Instant Deletion===  
  
On the second toolbarbutton, the attribute “client_onClick” allows you to register a client side “onClick” event handler. The attribute’s value is a snippet of JavaScript to pop-up a confirm dialog box. The prefix “client_” is an attribute naming convention to indicate that the event is handled at client side. The next attribute “onClick” allows you to register a server-side event handler. This means that when the toolbar button issues a “onClick” event, a closure will be invoked. If a user clicks the OK button on the confirmation dialog box, the “onClick” event will propagate to the server and deletes the clicked row from the grid’s data source. This causes the Grid to re-render and then instantly presents the result after deletion without reloading the whole page.
+
On the second ''toolbarbutton'', the attribute <code>client_onClick</code> allows you to register a client side ''onClick'' event handler. The attribute’s value is a snippet of JavaScript to pop-up a confirm dialog box. The prefix <code>client_</code> is an attribute naming convention to indicate that the event is handled at the client side. The next attribute ''onClick'' allows you to register a server-side event handler. This means that when the toolbar button issues an ''onClick'' event, a closure will be invoked. If a user clicks the OK button on the confirmation dialog box, the ''onClick'' event will propagate to the server and deletes the clicked row from the grid’s data source. This causes the Grid to re-render and then instantly presents the result after deletion without reloading the whole page.
  
 
[[File:instant_deletion_01.png|thumb|500px|none]]
 
[[File:instant_deletion_01.png|thumb|500px|none]]
Line 175: Line 182:
 
===Real Time Searching===
 
===Real Time Searching===
  
ZK also empowers the search function. If we type an existing id and click the search button, we can get the search result displayed in the grid immediately.
+
ZK also empowers search function. If we type an existing ''id'' and click the search button, we can get the search result displayed in the grid immediately.
  
 
[[File:real_time_searching_01.png|thumb|500px|none]]
 
[[File:real_time_searching_01.png|thumb|500px|none]]
  
But searching the race’s id is not practical in this example; instead we should search by name.
+
However, searching the race’s id is not practical in this example, we should search by name instead.
  
In list.gsp, replace <z:longbox id="idLongbox"/> with <z:textbox id=”keywordBox”/>.
+
In <b>list.gsp</b>, replace <code><z:longbox id="idLongbox"/></code> with <code><z:textbox id=”keywordBox”/></code>.
  
Add a variable Textbox keywordBox in the ListComposer.groovy file.
+
Add a variable <code>Textbox keywordBox</code> in the <code>ListComposer.groovy</code> file.
  
In the redraw() method:
+
In the <code>redraw()</code> method:
Comment out the 3 lines of code related to the idLongBox and add the following 3 lines:
+
 
 +
Comment out the 3 lines of code related to <code>idLongBox</code> and add the following 3 lines:
  
 
<source lang="java">  
 
<source lang="java">  
Line 196: Line 204:
 
</source>  
 
</source>  
  
Our search by name is done.
+
Now, our search by name is done.
  
 
[[File:real_time_searching_02.png|thumb|500px|none]]
 
[[File:real_time_searching_02.png|thumb|500px|none]]
  
You might think that ZK’s capability ends here. No, on the other hand, we can make the search result display more interactive.
+
You might think that ZK’s capability ends here? No, we can make the search result display to be more interactive.
  
Register an “onChanging” event handler by adding the following code in the ListComposer.groovy file:
+
Register an <code>onChanging</code> event handler by adding the following code in the <code>ListComposer.groovy</code> file:
  
 
<source lang="java">  
 
<source lang="java">  
 
void onChanging_keywordBox(InputEvent e) {
 
void onChanging_keywordBox(InputEvent e) {
keywordBox.value = e.value
+
keywordBox.value = e.value
redraw()
+
redraw()
}
+
}
 
</source>
 
</source>
  
Therefore, the method will be called when the value of keywordBox is changing.
+
The method will be called when the value of <code>keywordBox</code> changes.
  
Now we do not even need the search button, you’ll automatically get the search result when typing.
+
Now, we don't even need the search button, you’ll automatically get the search result when typing.
  
 
[[File:real_time_searching_03.png|thumb|500px|none]]
 
[[File:real_time_searching_03.png|thumb|500px|none]]
Line 221: Line 229:
 
<source lang="java">  
 
<source lang="java">  
  
void [eventName]_[componentId] (Event e){ … }
+
void [eventName]_[componentId] (Event e){  
 +
    …  
 +
}
  
 
</source>  
 
</source>  
Line 229: Line 239:
 
=Conclusion=
 
=Conclusion=
  
Although adopting AJAX can reduce the web applications’ response time thus improving user experience, communication complexity and various JavaScript libraries of AJAX constitute a barrier for most Grails developers and prevent them from using it. However, with ZK, developers are now able to build more interactive applications easily with many ready-to-use components and leave the communication issues behind. [1] Complete supported component list, http://xiaochong.github.com/zkui/manual/index.html
+
Adopting AJAX can reduce a web application's response time thus improving user experience and communication complexity but various JavaScript libraries of AJAX constitutes a barrier for most Grails developers preventing them from using it. However, with ZK, developers are now able to build more interactive applications easily with many ready-to-use components and leave the communication issues behind. See the complete supported component [http://xiaochong.github.com/zkui/manual/index.html list]. In the [http://books.zkoss.org/wiki/Small_Talks/2012/January/Enrich_Grails_Server_Pages_%28GSPs%29_with_ZK next article], I will demonstrate how you can combine all the functions of the 3 GSPs into one page.
 +
 
 +
= Reference =
 +
<references/>
 +
 
 +
=Resources=
 +
 
 +
*View the [http://code.google.com/p/zkuiexample/source/checkout source code]
 +
*Download the [http://zkuiexample.googlecode.com/files/racetrack.war WAR file]
 +
 
  
 
{{Template:CommentedSmalltalk_Footer_new|
 
{{Template:CommentedSmalltalk_Footer_new|
 
|name=Potix Corporation
 
|name=Potix Corporation
 
}}
 
}}

Latest revision as of 04:19, 20 January 2022

Ajax GSP with ZK

Author
Hawk Chen, Engineer, Potix Corporation
Date
January 16, 2012
Version
ZK 5

Introduction

Grails is an open-source web application framework based on the Groovy language. Not just purely a framework, Grails also provides a highly productive development mode including web server, automatic reload of resources and seamless integration with two other best practices, Spring and Hibernate. Grails Server Pages (GSP), which is an evolution from Java Server Pages (JSP) is Grails’ primary view technology.

Compared to JSP, GSP helps simplify implementation procedures and usage of custom tag libraries. It uses "SiteMesh" application framework for page decoration.Please note that only some JavaScript libraries (Prototype and Scriptaculous) can be supported out of the box when utilizing Ajax with GSP. Therefore, developers may have to deal with tedious Ajax details and various JavaScript API integration issues and this is why ZK comes in handy. With the use of a Grails plugin - zkui, developers now empower their level of GSP usage with Ajax by embedding ZK UI components.

This article will demonstrate how ZK can enhance the interactivity of GSP with Ajax. To get a better understanding of this article, it is recommended for readers to know the basic concept of Grails, such as domain class, controller, GSP, and Groovy. The development environment is under Eclipse 3.6, SpringSource Tool Suite 2.7.1., Grails Support 2.7.1., Grails 1.3.7., Groovy-Eclipse Plugin 2.5.1 and zkui 0.3.2.

Ajax GSP with ZK

Prepare Environment

  1. To create a Grails project, we need an eclipse plugin – SpringSource Tool Suite. Click here to download
  2. Install Grails Tools, which is a SpringSource Tool Suite extension. Click here to download
  3. You must install three items: Grails, Grails Support, and Groovy Eclipse

Application Example Background

We are going to build a simple web application called "RaceTrack". "RaceTrack" is designed for a running club which holds several races. The purpose of this example is to show how users of the running club can easily manage their held races through creating, updating and deleting records.

Create a Project

To create the "RaceTrack" project , use eclipse File\New\Grails Project or SpringSource Tool Suite\Create\Grails Project. You must install the zkui plugin in order to harness the power of ZK components.

Right click the "RaceTrack" project in Eclipse and hover to Grails Tools. To install the zkui plugin, type “install-plugin zkui” at the Grails Command Prompt window or search it with the Grails Plugin Manager.

Installation msg.png

You can see the installation message at the Console View. After the plugin is installed, we can start to implement our application.

Create a Domain Class

At the beginning of the implementation process, you have to create a domain class to represent a race and manually add some properties and validation constraint. (Select Grails Tools\Create Domain Class)

 

class Race {
    String name
    Date startDate
    String city
    Integer distance
    Integer cost
    static constraints = {
		name(blank:false, maxSize:50)
		city(inList:["Taichung","Tainan","Kaohsiung"])
		distance(min:0)
		cost(min:0, max:100)
    }
}

Static Scaffolding

With zkui static scaffolding, we can complete the four basic functions: Create, Read, Update and Delete (CRUD) without writing any code. Type "zkui-generate-all racetrack.Race" at the Grails Command Prompt window and zkui will generate 3 GSPs, 1 controller, and 3 composers (under grails-app\composers). To render ZK components in a GSP, you need to add <z:resources/> in the <head> of grails-app\views\layouts\main.gsp.

Static scaffolding.png

Let’s take a closer look at these generated artifacts. The controller class has no big difference with the original Grails controller,but GSP is filled with tags with a prefix “z”. Those tags represent the ZK UI components. The tag name is the component’s name. ZK provides more than 200 components and zkui supports most of them [1] Each GSP has a <z:window> to enclose all ZK components, and the window’s attribute “apply” specifies which composers to handle their events.

 

 <z:window style="padding:5px" apply="racetrack.race.ListComposer">

Hence in list.gsp, the ListComposer will handle events from all components inside <z:window> including the window itself.

Now, run the application and visit the page via the link http://localhost:8080/racetrack/race/create, you will see a form composed by ZK components corresponding to each Race class’ property. We fill out the form partially and then click the “Create” button. Then we can see the validation message pop-up instantly without reloading the page. Now, this GSP is powered by Ajax.

Validation msg.png

Among all the generated artifacts, the composers under grails-app\composers are unfamiliar to Grails developers. This term “composer” comes from ZK. It plays the same role as the Grails controller in a MVC pattern, with a difference in which Grails controller handles requests from GSP while the composer of ZK only handles events issued from ZK components. Another notable difference is that the composer can manipulate ZK components on GSP which we will talk about in the next section.

Composer in Depth

There are 3 composers, and each of them corresponds to one GSP which can be easily identified by its naming. Open ListComposer.groovy which handles events from list.gsp. Let’s first look at these variables.

ListComposer.groovy

Grid grid
Paging paging
Longbox idLongbox

It seems normal, but you’ll find that there are three ZK components whose variable names are identical to that of ZK component tag’s id attribute in list.gsp. This is not a coincidence, it is a feature of the composer called component Auto-wiring. It is automatically enabled by mapping a naming convention and a variable type. Each ZK component has a corresponding class (ex: <z:grid> is org.zkoss.zul.Grid), and if you put the correct name and type in the composer upon your component tag, the zkui plugin will wire components for you. Through these variables we can manipulate ZK components in a composer. In fact, static scaffolding has already done it for you.

You can see a closure afterComposer. This closure is called when all ZK components and its descendants are instantiated and rendered. So we usually do some post-processing to components in it.


ListComposer.groovy

 

def afterCompose = {Component comp ->
        grid.setRowRenderer(rowRenderer as RowRenderer)
        grid.setModel(listModel)
        redraw()
    }
  • Line 2 sets a custom row renderer to grid component and this means that we can draw each row by ourselves.
  • Line 3 attaches a data source that will be used in the renderer.


Then, we look inside the redraw() method:

ListComposer.groovy

 

    private redraw(int activePage = 0) {
        int offset = activePage * paging.pageSize
        int max = paging.pageSize
        def raceInstanceList = Race.createCriteria().list(offset: offset, max: max) {
            order('id','desc')
            if (idLongbox.value) {
                eq('id', idLongbox.value)
            }
        }
        paging.totalSize = raceInstanceList.totalCount
        listModel.clear()
        listModel.addAll(raceInstanceList.id)
    }
  • Line 4 constructs a race list upon search criteria. The only criterion is the race id which we can retrieve from the ZK component by the use of idLongbox.value, we can get the user's inputted id in the textbox.
  • Line 12 changes the Grid’s data source and will cause the grid to re-render.


ListComposer.groovy

 

    private rowRenderer = {Row row, Object id ->
        def raceInstance = Race.get(id)
        row << {
                a(href: g.createLink(controller:"race",action:'edit',id:id), label: raceInstance.id)
                label(value: raceInstance.name)
                label(value: raceInstance.city)
                label(value: raceInstance.distance)
                label(value: raceInstance.cost)
                label(value: raceInstance.startDate)
                hlayout{
                    toolbarbutton(label: g.message(code: 'default.button.edit.label', default: 'Edit'),image:'/images/skin/database_edit.png',href:g.createLink(controller: "race", action: 'edit', id: id))
                    toolbarbutton(label: g.message(code: 'default.button.delete.label', default: 'Delete'), image: "/images/skin/database_delete.png", client_onClick: "if(!confirm('${g.message(code: 'default.button.delete.confirm.message', default: 'Are you sure?')}'))event.stop()", onClick: {
                        Race.get(id).delete(flush: true)
                        listModel.remove(id)
                    })
                }
        }
    }

We use rowRenderer to customize Grid’s rendering. For example, to create a ZK component dynamically, zkui provides a leftshift (<<) operator to append a child to each row. The id comes from the grid’s data source. According to the code after line 3, you can see how it adds a link, 4 labels, and 2 tool bar buttons (update, delete) in a row.

Customise grid.png

Instant Deletion

On the second toolbarbutton, the attribute client_onClick allows you to register a client side onClick event handler. The attribute’s value is a snippet of JavaScript to pop-up a confirm dialog box. The prefix client_ is an attribute naming convention to indicate that the event is handled at the client side. The next attribute onClick allows you to register a server-side event handler. This means that when the toolbar button issues an onClick event, a closure will be invoked. If a user clicks the OK button on the confirmation dialog box, the onClick event will propagate to the server and deletes the clicked row from the grid’s data source. This causes the Grid to re-render and then instantly presents the result after deletion without reloading the whole page.

Instant deletion 01.png
Instant deletion 02.png

Real Time Searching

ZK also empowers search function. If we type an existing id and click the search button, we can get the search result displayed in the grid immediately.

Real time searching 01.png

However, searching the race’s id is not practical in this example, we should search by name instead.

In list.gsp, replace <z:longbox id="idLongbox"/> with <z:textbox id=”keywordBox”/>.

Add a variable Textbox keywordBox in the ListComposer.groovy file.

In the redraw() method:

Comment out the 3 lines of code related to idLongBox and add the following 3 lines:

 

if (keywordBox.value){
    ilike('name',"%"+keywordBox.value+"%")
}

Now, our search by name is done.

Real time searching 02.png

You might think that ZK’s capability ends here? No, we can make the search result display to be more interactive.

Register an onChanging event handler by adding the following code in the ListComposer.groovy file:

 
void onChanging_keywordBox(InputEvent e) {
	keywordBox.value = e.value
	redraw()
}

The method will be called when the value of keywordBox changes.

Now, we don't even need the search button, you’ll automatically get the search result when typing.

Real time searching 03.png

Register an event handler in a composer is to make the method name follow the naming convention:

 

void [eventName]_[componentId] (Event e){ 
     
}

It is quite simple.

Conclusion

Adopting AJAX can reduce a web application's response time thus improving user experience and communication complexity but various JavaScript libraries of AJAX constitutes a barrier for most Grails developers preventing them from using it. However, with ZK, developers are now able to build more interactive applications easily with many ready-to-use components and leave the communication issues behind. See the complete supported component list. In the next article, I will demonstrate how you can combine all the functions of the 3 GSPs into one page.

Reference

  1. Grails ZK UI Plugin - Reference Documentation http://xiaochong.github.com/zkui/manual/index.html

Resources


Comments



Copyright © Potix Corporation. This article is licensed under GNU Free Documentation License.