Sunday, June 1, 2008

Make gsp readable with grails templates and taglibs

In one of my previous post I already explained how grails templates and taglibs can simplify your gsp files and make them more readable. Now I believe I made even step further. One of the reasons I like grails is that front end technology is solved very good and is easy to understand even for java back-end developers like me. My gsp files does not look like html files but more like collection of components. The reason is simple. With grails it is very easy to create templates and tags. Example in this post is taken from www.grailstutorials.com, portal of grails and groovy community on which I work in my free time. Let me try to explain mind flow. I wanted to display components like one on the picture in common and easy to read way.

stats

The first solution that came to my mind was really simple. Thing like this one you can solve easily in this way:

<div class="messageBox">
<div class="msg_box_title">
<label>TITLE_HERE</label>
</div>
<div class="msg_box_body">
CONTENT_HERE
</div>
</div>

But in the sea of the divs it is really hard to orientate and the gsp looks more complicated than it really is. So I start thinking how it would be nicer. And I realized that what I want to achieve so my code is easier to read is following:

<g:messageBox title="TITLE_HERE">
CONTENT_HERE
</g:messageBox>

So as the first thing I created message box template.

<div class="messageBox">
<div class="msg_box_title">
<label>${title}</label>
</div>
<div class="msg_box_body">
${body}
</div>
</div>



This code is almost the same as the first code. Important things to notice are model variables ${title} and ${body}. Now when I had a template I needed possibility to display it with the messageBox tag. So the next thing to create was to create tag. Just create simple tag file, if you don't know how read the post mentioned at the begging. And the code of the tag is:



def messageBox = {attrs, body ->
out << render(template:"/templates/common/messageBoxTemplate", model:[title:attrs.title, body:body()])
}



The only good thing to notice in the code above is usage of body() as a value of body model parameter instead of body that came as a input value into messageBox. Reason for this is that we don't want to send body closure to the template but content of the body closure.



Having messageBox tag available, the first code example in this post can be specified in the gsp file as:



<g:messageBox title="TITLE_HERE">
CONTENT_HERE
</g:messageBox>



exactly as we wanted.



Now let us think about CONTET_HERE part. If we put complex gsp code there we will not get too much in readability. But solution is very simple. Don't use complex gsp code there, create corresponding template and tag for that part and you gsp code will be easy for reading. Just to give you example of what I have in mind, this is code snippet I use in grailstutorials.com to display statistics (you can see the picture on the top of post):

<g:messageBox title="Stats">
<g:dataInfo/>
</g:messageBox>

I believe that the final result is really easy to understand.

4 comments:

Fred Janon said...

I like the idea of making Grails more component oriented on the presentation side. Do you plan to make your Grails project "www.grailstutorials.com" open source? I like the layout and I am wondering how you did it and what you used.

Thanks

Fred

jan said...

@Fred
To be honest so far I didn't think about making http://www.grailstutorials.com open source project. What I planned is to write post for each interesting part during development with implementation details so anybody can gain something from my experience.

But I will also think to make www.grailstutorials.com open source.

Anonymous said...

Great tips. Questions I have is how does the template and tag you wrote for the content portion get it's data. For example, how does it get the number of users? Do you have to do the database lookup everytime you render a view?

jan said...

On grails and groovy tutorials I actually do direct database access when rendering view.

But it is also possible to store and maintain this information in the application variable that is accessible from the tag.

You can have a look on the post getting data into tags and templates