Wednesday, February 13, 2008

Example of template and taglib with grails

In this example I will show how templates and taglibs can be used to create components.
Imagine that you are creating application for managing projects. When working with an application you are always working within a scope of project. So all the time you need to be able to change project you are working with. So excellent place for selection would be top of the each page within application. So lets go through steps creating such application.

To create project in the command line type:
grails create-app project_manager

Then create Project domain class:
grails create-domain-class Project

Change the code of Project class so it looks this way:

class Project {
String title
String description

static constraints = {
title(blank:false, unique:true, nullable:false)
}
}

To generate controller and views for Project class use:
grails generate-all project

This should be enough to be able to start application with "grails run-app" and then open http://localhost:8080/project_manager

Well, my intention is only to place combo box somewhere on the top of the page so you can select project with which you want to work. To find out how to remember selection within session scope take a look at my post. That part will be skipped here.

Se lets return to the problem. We want to have possibility to display combo box that will enable user to select project with which she wants to work.

Let start with the simplest solution.

I will change the grails-app/views/layouts/main.gsp by adding before <g:layoutbody> following :

<g:form controller=\"project\">

<g:select name=\"project.id\" from=\"${Project.list()}\" value=\"${session.projectId}\">

<g:actionsubmit class=\"edit\" value=\"Select\" action=\"selectProject\">

</g:actionsubmit>
</g:select></g:form>

Simple enough and solves my problem. But later on, if I change my mind and don't want to have possibility to select project on each page but only from some pages, I will have to copy/paste given code to all pages. It is not so complicated, but may be a problem if I want to change something within those 4 lines of code. In that case I would have to change it in lot of places. It means something has to be changed.

Let create template from given code snippet.

Luckily, creating templates with grails is simple enough.

Create file _projectSelectionTemplate.gsp and place it to e.g. grails-app/views/common.
Code within this template is the same as one added to the main.gsp

Now it is time to update our main.gsp file. Old part of project selection exchange with following line:

<g:render template="/common/projectSelectionTemplate"/>

This is for sure simplier and easier to understand than the first version of project selection.
But still, this structure with <g:render.... looks little bit strange.
So let simplified it even more :)

Let create tag lib that can be reused.

So create grails-app/taglib/ProjectSelectionTagLib.groovy file.

Content of this file should be:

class ProjectSelectionTagLib {
def selectProject = {attrs, body ->
out << render(template:"/common/projectSelectionTemplate")
}
}


This way we have defined tag selectProject that will render template _projectSelectionTemplate.

Now, I can even more simplify main.gsp.

Change <g:render... part with the following:

So the final result is:

<g:selectProject/>

This is now very simple, we have tag that can be reused in any place where we need it and it is easy understandable.
Lot of things can be accomplished this way and it is obvious that grails is good web framework because everything seems to be so easy :)

5 comments:

Unknown said...

Nice write up. Thanks for the ideas.

Anonymous said...

so bored

Mohamed Fouad said...

Thank you for this, I think I am going to standarize my gsp development in this way, if you ever found a better approach using Grails please share :)

Thanks again, Great effort :)

Federico said...

Thank you for another illuminating post! Your posts are helping me a lot getting started with grails!

Unknown said...

This illustration of combining templates and taglibs was very helpful. Thank you.