tags:

views:

61

answers:

3

Please pardon this newbie question...

In Grails, if I want a partial to be embedded in a layout so that it appears globally, which requires live data, let's say a list of categories, where is the best place to pull the category data to feed it into the view?

I realize this is a very basic question, but I haven't seen this covered in any tutorials yet.

A: 

You want to put it in grails-app\views\layouts\main.gsp. That's the default layout that most generated code (and likely most examples that you'll see) will use.

Check out the sitemesh section of the grails documentation.

Ted Naleid
A: 

I think you're trying to ask... "How do I feed the category data to the view when I don't know which action caused the page to render, so the action can't add the data to the model?" If that's so, you can use Groovy code directly in the ${} block, such as:

<g:each in="${ Category.findAll() }" var="cat" />

Note that findAll is added to every Model class, and can be called statically (via the classname, not an instance).

Hope this helps

Bill James
Thanks Bill. I thought of that, but wasn't sure if it was appropriate to call a method in the model directly from a view.
Thody
Well, it's not the strictest MVC, but it's not like you're putting the SQL in there. You'll find the sample Grails stuff does this all the time.
Bill James
A: 

I started this as a comment to Bill James's answer but I figured it might be longer. Bill suggeseted using groovy code inside ${} to make the template (called partial in Rails) work globally:

<g:each in="${ Category.findAll() }" var="cat" />

But, you should not just add code if you dont feel like it might mess up your tidy xml/html. You can always put it in a closure inside a TagLib and thus make it a Tag. The closure must have no parameters, or an 'attr' parameter, or an 'attr' and 'body' parameters but other signatures are invalid.

class CustomTagLib {

 static namespace = 'cus'

    def categories = { attr, body ->
      g.each( in: Category.findAll(), var: attr?.var ?: 'categories' )
    }

}

Then you can use that tag into the template with the namespace you chose:

<cus:categories />

Personally I prefer using tags since most of the time it is a reusable code, so it's better for not violating the DRY principle.

Azder
Thanks Azder. Both approaches work obviously, but your taglib approach feels more MVC "correct", so I'm going to go with that. Thanks!
Thody