Wednesday, October 27, 2010

Grails and rendering different content types

Hi there Grails freaks!

I've discovered something ground breaking (well, at least for me) with the way Grails renders views so I thought I'll share it with the class :)

Imagine you have a controller, say a PersonController for example. And there you have the "get" action that returns just enough data to render the view. Well times are different than what they used to be 3-4 years before and HTML is not the one and only output format we expect these days. There's JSON, plain text, ATOM, RSS - you name it! Back to the original thought...

Knowing that the JSON format for example looks different than the HTML one (no surprise there) it's kind of obvious the way it's being rendered will need to be different. So for example an HTML view will have everything embedded into an <html> element, then there will be a <body> item containing whatever needs to be rendered whereas the JSON version will most probably contain only the key-value map in JavaScript format.

So what's so ground breaking here? We all know there's this "render person as JSON" thingy, right? Do we really need anything else?

As a matter of fact we do. There are lots of examples where JSON generated this way will not cut it. For example you need the actual data wrapped into some outer object, maybe some additional "count"-like field for list is something you need... You name it!

To get around this here's the revelation: you create not one but as many views as you need but add the extension to their names, for example for the "get" action of "person" controller you'd have get.gsp for the HTML view of the thing and a "get.js.gsp" view for the JSON representation!

Of course one always needs to remember to set the content type properly:

<%@ page contentType="text/javascript"%>

I have no idea if this works with any other version of Grails other than 1.3.5 (this is what I've tested) but this feature is so nice it will allow for effortless rendering of different types of results with no pollution in controller code.

Here is an example project that does what I've described. Once you've got it up and running navigate to http://localhost:8080/example/home/index and http://localhost:8080/example/home/index.js to see the results.

Have fun!

No comments: