Tuesday, April 18, 2006

Grails: The Render method and Ajax

Users of Ruby on Rails will be familiar with the 'render' method which allows rendering of responses from a controller. Grails has a similar mechanism, for example rendering text is as simple as:


render 'hello world!'
or
render(text:'world',contentType:'text/xml')


You can of course also render templates and views via the method (for more complete documentation see here), but what makes Grails' render method that little bit different is its support for markup building.

With other Java frameworks I've used I ended up with loads of partial views implemented as JSP or velocity views. Each with the sole responsibility of rendering some XML or JSON. With Grails this is rarely needed for pure XML responses (note, I would never condone defining layout in this way this is purely for data oriented XML rendering). Rendering XML is made infinitely more simple:


def results = Book.list()
render(contentType:'text/xml') {
books {
for(b in results) {
book(title:b.title)
}
}
}


The above results in the following XML snippet being rendered to the response:


<books>
<book title="The Shining" />
<book title="Along came a Spider" />
</books>


When you combine this with how Grails controllers reload automatically on changing it makes writing ajax responses a breeze. But, there is more! Grails has inbuilt support for OpenRico so if you want to write Ajax responses in Ricos required format this can be done as follows:


render(builder:'rico') {
object(id:'bookUpdater') {
books {
for(b in results) {
book(title:b.title)
}
}
}
}


Rico will then automatically look-up your 'bookUpdater' instance and delegate the response to it passing the contained XML to the updater for handling.

I don't normally like talking about unimplemented features, but thought it might be worthwhile just to highlight the power of the builder concept in Groovy as I don't believe that many grasp the potential of builders and their usages. One of the upcoming features in Grails is a JSON builder which will be available via the render method so say I wanted to render JSON instead of XML? We just change the content type defined in the render method:


render(contentType:'text/json') {
books {
for(b in results) {
book(title:b.title)
}
}
}


And the resulting output would be JSON instead of the XML without any change to the structure of the builder code itself:


{
books : [
{ title: 'The Shining' },
{ title: 'Along came a spider' }
]
}

2 comments:

Anonymous said...

its xml, so you must close all tags:
<book ... />

ph.charriere said...

Hi,
how can i update value of an input type="text" with ajax and a controller method ?

i've tried with the rico builder but i've not the good synthax

thanks