RSS Feed
Download our iPhone app
Browse DevX
Sign up for e-mail newsletters from DevX


Going Live with a Grails-Powered Blog : Page 4

Once you have built a Grails project, how do you deploy it? Learn how to use Groovy builders, filters, and tags to deliver a Grails project. Along the way you'll delve into AJAX and deploy a Grails application in Tomcat.

Simple Tagging with AJAX
Grails provides AJAX support through the following set of tags:
  • remoteLink: calls a remote function when the link is clicked
  • remoteField: creates a field that sends updates to the server automatically
  • formRemote: performs AJAX for submission (falling back to normal form submission if JavaScript is not enabled)
  • remoteFunction: assigns a remote JavaScript function to DOM events

To demonstrate some of these tags, you will add tagging to the blog. To add tagging to posts, you will need to make the changes to the domain shown in Listing 6. The changes to the Post class are highlighted in bold.

The areas of interest in Listing 6 are the creation of a many-to-many relationship and the use of the "?." operator. The many-to-many relationship is created by having a static hasMany property on the tag and the post. Behind the scenes, Grails will create a linking table in the database to allow this many-to-many relationship to be persisted in the database. The belongsTo property should be put on the post end of the relationship to allow a save() call on a post to cascade to the tags to which the post is related. The "?." operator performs an implicit null check on the object before calling the method or property specified, which avoids having to perform a large number of null checks in the code.

Next, you need to add a field to the edit.gsp file for posts to enter tags as a space-separated string:

  <g:textField name="tagString" value="${post.tagsAsString()}" cols="50"/>

When this field is in place, the PostController needs to be updated to handle creating tags and displaying posts by tag. Listing 7 also shows the PostService you should create to extract some logic from the controller.

The PostService is created to extract the loadPost logic that was in the controller and to add the space-delimited list of tags to a Post. Remember that defining the postService property in the controller will automatically inject the PostService. The save action is updated to allow the tags to be added to the post. A new listByTags action is added to allow all posts for a given tag to be loaded. You will notice that this action assumes the ID property in the params map is actually the tag name:

def tag = Tag.findByName(params.id)

The reason for this is that you can create meaningful URLs that are readable, such as:


This URL will show all posts tagged with java, and it is more intuitive than:


To help with manual testing, you should add some tags to the posts that are created in the BootStrap class (see Listing 8).

Finally, you need to display tags on the post list page. To do this, you must create a filter that will add the full list of available tags to the model, create a tag to list the tags for a post, and update the post list page to display tags. Listing 9 shows how to do this.

The tags filter is configured to execute for every action in the site. You use the after closure to add the full list of tags to the model created by the action. You use the "?." operator for this because the model could be null if a redirect is issued. The tag library class will iterate over a list of tags and create a list of space-delimited links to the listByTag action on the post controller. In the list GSP, the webRequest, a Grails-specific request object (GrailsWebRequest), is used to determine which action has rendered this page to determine if the tag name should be displayed. The formatDate tag has been used to improve the readability of the published date of the post, and the new tagLinks tag is used to render the links to the tags for a post. Finally the layout, blog.gsp, must be updated to display the list of available tags on the right of the page:

<div id="rightnav">
    <g:each var="tag" in="${tags}">
      <li><g:link controller="post" action="listByTag" id="${tag.name}">${tag.name}</g:link></li>

If you run the application now, you will see tags displayed on the list page and you will be able to add tags to and remove tags from a post (see Figure 5) through the post edit page (see Figure 6).

Figure 5. Post List Page With Tags: You should be able to see tags displayed on the post list page.
Figure 6. Editing Tags For A Post: You can now add and remove tags for a post through the edit page.

Improving Tagging with AJAX
To demonstrate the Grails support for AJAX, you can enrich the management of posts by allowing users to edit tags inline on the post list page. You will need to create two templates and add three new actions to the PostController. The Grails AJAX tags you will use are:

  • remoteLink: to load templates in using AJAX requests
  • formRemote: to allow the changes to the list of tags to be submitted using AJAX

Templates are used to separate out common chunks of view code into reusable fragments. They are especially useful when working with AJAX, as they allow you to easily replace discreet portions of the view as the result of a request. Templates are similar to views in that they exist in the grails-app\views\<domain> folder. The convention for naming templates is to create them with an underscore at the start of the filename. Create the two templates _showTags.gsp and _editTags.gsp under the grails-app\views\post directory with the code from Listing 10.

The showTags template displays the tags for a post as before, but also provides a link that will call the editTags action on the post controller through an asynchronous JavaScript request. The attributes of the remoteLink tag are very similar to the Grails link tag you have used before. The controller, action, and id attributes tell the tag to which action the request must be submitted. The big difference is the update attribute. This tells the AJAX-handling code generated by the tag which HTML element to update with the result of the AJAX request.

The editTags action will render the editTags template, which creates a form allowing tags to be edited in place of the current list of tags. The editTags template renders a form that will submit its data through an AJAX call. The formRemote tag specifies the URL to submit the asynchronous request to, while the use of the controller and action attributes are the fallback location to submit an HTTP request to in case JavaScript is not enabled. Another remoteLink is used to reload the list of tags if the user wishes to cancel the update.

To allow the list page to use AJAX, you must include the following in the HTML <head> tag:

<g:JavaScript library="prototype"/>

This tells Grails to use the Prototype JavaScript library.

Additionally, to add the new actions to the controllers, replace the line that currently shows the tags for a post:

<p>Tags: <gp:tagLinks tags="${post.tags}"/></p>

With the following:

<div id="tags${post.id}">
	<g:render template="showTags" model="[post:post]"/>

The following are the three new actions to handle updating tags:

def editTags = {

def saveTags = {
  def post = postService.loadPost(params.id)
  postService.populateTags(post, params.tagString)
  if(post.save()) {
    render(template:"showTags", model:[post:post])
  } else {
    render("Save failed")

def showTags = {
  render(template: 'showTags',
      model: [post: Post.get(params.id)])    

The editTags action handles the rendering of the editTags template, just as the showTags action renders the showTags template. The saveTags action loads the identified post and adds the tags to the post before saving the post and then rendering the showTags template.

If you now run the application you should have a link to edit tags on the post list page (see Figure 7). Clicking this link will load a form that allows you to edit the tags inline (see Figure 8).

Figure 7. Edit Tags Link: Tags can be edited from the post list page.
Figure 8. Edit Tags Inline: Tags can be edited inline on the post list page.

Close Icon
Thanks for your registration, follow us on our social networks to keep up-to-date