Question

I have different kinds of html emails i want to send to my users, but each email uses the same layout (emailLayout.gsp). I need to render this emails (gsp) to string, to send them via an email method.

Using this code this does work, but i need it working with the groovyPageRenderer.render() method, because i need to send emails in a grails filter or service (the above 2 outcommented examples doesn't work):

    //def emailContent = groovyPageRenderer.render(view: '/email/emailConfirmation', model: [userInstance: userInstance])
    //def emailContent = g.render(view: "/email/emailConfirmation", model: [userInstance: userInstance])
    def emailContent = g.include(view: "email/emailConfirmation.gsp", model: [userInstance: userInstance])

Using groovyPageRenderer doesn't include my layout html, only the emailConfirmation.gsp content gets rendered. So header and footer from my emailLayout.gsp is missing. Why doesn't groovyPageRenderer.render() renders the full gsp WITH layout?

Thanks for your help!

Was it helpful?

Solution

Here is a helpful post about the use of groovyPageRenderer by mrhaki: http://mrhaki.blogspot.de/2012/03/grails-goodness-render-gsp-views-and.html

It actually demonstrates the use with the example of rendering an email confirmation. It also states why Sitemesh does not work.

We can use tags from tag libraries in our GSP views and templates. The Sitemesh layouts cannot be used. The PageRenderer works outside of the request scope, which is necessary for the Sitemesh layouts.

So if it is not possible to use Sitemesh you have to rearrange your templates. You could for example put your layout in a GSP emailConfirmation

<g:render template="/email/header" />
<g:render template="/email/emailConfirmation" />
<g:render template="/email/footer" />

But since you have several email templates using a common layout this approach would get very repetitive. Instead you could have a GSP emailLayout like this

<g:render template="/email/header" />
<g:render template="${templateName}" />
<g:render template="/email/footer" />

and pass a fitting model from your service

def emailContent = groovyPageRenderer.render(view: '/email/mailLayout', model: [templateName: '/email/emailConfirmation', userInstance: userInstance])

This way you could reuse your layout for different email templates.

Or you render the content in a first step and pass it to the template

def confirmation = groovyPageRenderer.render(template: '/email/emailConfirmation', model: [userInstance: userInstance])
def emailContent = groovyPageRenderer.render(view: '/email/mailLayout', model: [content: confirmation])

where it is output

<g:render template="/email/header" />
${content}
<g:render template="/email/footer" />
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top