Enrich Grails Server Pages (GSPs) with ZK

From Documentation
Revision as of 00:13, 15 May 2012 by Sphota (talk | contribs) (corrected date from 2011 to 2012)
DocumentationSmall Talks2012JanuaryEnrich Grails Server Pages (GSPs) with ZK
Enrich Grails Server Pages (GSPs) with ZK

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

Introduction

When developing a web application with AJAX, we tend to combine multiple related functions into one page instead of separating them into different pages. On the other hand, when developing with JSP/GSP, page-based design style is usually adopted because submitting a request will send all the data on the page to the server and response will reload the whole page. Hence, there can’t be too much information on one page otherwise the application response time will increase.

However, when AJAX comes into play, the design style changes because AJAX helps developers to send and receive less data for each user interaction, which means that more functions can be added to one page with more UI controls. This way, users can trigger different functions by different UI controls without the need to wait for the whole page to reload. The major benefit of this is that it makes a web application more like a desktop application.

Our example application “RaceTrack” has 3 GSPs and each of them provides a different function. Our goal is to combine all the functions into one page.

Preparation

list.gsp provides search and deletion in an AJAX way, but to create and/or edit a race, users are still required to wait for the reloading of another page. These two functions do not benefit from AJAX. Now, we are going to present how users can combine the 3 GSPs into one using AJAX.

As list.gsp contains more functions than others, we decided to use it as the base to build the combined page on it. We plan to combine all functions into fusion.gsp.

Duplicate list.gsp and rename it to fusion.gsp.

Modify <z:window> attribute “apply” as following:

  <z:window apply="racetrack.race.FusionComposer"/>

Create the corresponding composer

  • Duplicate ListComposer.groovy and rename it to FusionComposer.groovy.
  • Open FusionComposer.groovy and change class name to FusionComposer.

This means that we assign Fusion Composer to handle all events from <z:window> and its child components.

Combine the Functions

Add an Action in RaceController.groovy

def fusion = {
		def raceInstance = new Race()
		raceInstance.properties = params
		return [raceInstance: raceInstance]
	}

Combine Creation

To enable creation feature, we design a form in a similar manner to the form in create.gsp for user input.

  1. Copy all ZK components inside <z:window> (excluding window itself) in create.gsp and paste after <z:paging> in fusion.gsp.
  2. Change button id from “saveButton” to “createButton” and remove “Race List” button.
  3. Copy variable “Window self” from CreateComposer.groovy to FusionComposer.groovy.
  4. Copy method “onClick_saveButton” from CreateComposer.groovy to FusionComposer.groovy.
    Rename it to “onClick_createButton”
    Remove redirect( ) method calling
  5. Add redraw() at bottom of onClick_createButton()

Now the “Create” button works as expected. However, after creating a race, the original data in the text remains. This may bother users as they will need to manually delete the texts. Therefore, we add a method to automatically clear the data in the textbox in which it will be called after creation.

Enrich Grails Server Pages with ZK 01.png

Clear Input

To clear input fields, we need the help of component auto-wiring. To enable this feature, add the “id” attribute to each input component and declare the variable names as same type as input fields.

	Textbox nameBox
	Combobox citySelect
	Intbox distanceBox
	Intbox costBox
	Datebox startDateBox

We can clear user input by manipulating these components’ values.

void clearInput(){
		nameBox.value = null
		citySelect.selectedItem = null
		distanceBox.value = null
		costBox.value = null
		startDateBox.value = null
	}

Call this method inside onClick_createButton() after redraw().

Combine Update

Add an update button next to the create button and a variable “Button updateButton” in FusionComposer.groovy To avoid confusing users with 2 buttons, we make the update button invisible by setting the attribute visible to false.

<z:button id="updateButton"
label="${message(code: 'default.button.create.update', default: 'Update')}" visible="false"/>
When updating a race, it needs “id” and “version”, we add two fields from edit.gsp
Copy 2 Longboxes with name “id” and “version to fusion.gsp and set attribute “id” as follows:
<z:longbox id="idBox" name="id" value="${raceInstance.id}" visible="false"/>
<z:longbox id="versionBox" name="version" value="${raceInstance.version}" visible="false"/>

You can put 2 Longboxes anywhere inside <z:window>, and we recommend to put them before <z:grid>. Declare 2 variables in FusionComposer.groovy for them.

	Longbox idBox
	Longbox versionBox

The design pattern is as follows: when users click the edit button in any row, the update button appears, the create button becomes invisible, and transfer selected row’s data into each input field. So, we have to do these actions inside the “onClick” event handler for edit button.

Modify the code about toolbar button creation inside rowRenderer closure as follows:

	onClick:{
idBox.value = raceInstance.id
versionBox.value = raceInstance.version
		nameBox.value = raceInstance.name
		citySelect.selectedItem = citySelect.items.find { it.value == raceInstance.city }
		distanceBox.value = raceInstance.distance
		costBox.value = raceInstance.cost
		startDateBox.value = raceInstance.startDate
		updateButton.visible = true
		createButton.visible = false	
	})

We remove href attribute and add onClick attribute with a closure.

To make update button work, we create an event handler based on onClick_saveButton() in EditComposer.groovy

  1. Copy void onClick_saveButton(Event e) in EditComposer.groovy to FusionComposer.groovy
  2. Rename the method to void onClick_updateButton(Event e)
  3. Remove all redirect()
  4. Call redraw() and clearInput() at the end of the method like onClick_createButton()

After the update, switch back to creation function, so make update button invisible and create button visible.

The final result of onClick_updateButton(Event e) will be as follows:

void onClick_updateButton(Event e) {
		...
		redraw()
		clearInput()
		updateButton.visible = false
		createButton.visible = true
	}

The update function is now completed.

Enrich Grails Server Pages with ZK 02.png

Live Demo

ZK Enrich Your Pages

One of the most criticized points of page based web application design is the bad user experience it brings about. People are tired of long response times and also having to find desired functions by switching in between pages. Consequently, embedding more functions into one page makes your web application more powerful, convenient and competitive to desktop applications. With this as the ultimate goal, ZK is the best way to enrich your application.

Resources


Comments



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