MiKo
MiKo

Reputation: 2146

Grails <g:set> tag not executed inside custom tag

I have a custom tag called <mk:pageViewTag> which first renders .gsp template and then executes its body inside:

Taglib (UtilTagLib.groovy):

string namespace = "mk"

def pageViewTag = { attrs, body ->
    out << render(template: '/templates/pageTagView') {
        body()
    }
}
...

Template I render (templates/_pageTagView.gsp):

<body>
    ${ body() }
    ...
</body>

GSP I use custom tag on (test.gsp):

<mk:pageViewTag>
    <g:set name="test" value="${1}">
    ${test?:0} %{--Here, I got 0. Variable test does not exist!--}%
</mk:pageViewTag>

Everything works perfectly except for <g:set> tag, which does not perform as I expect. Grails simply cannot see the variable I declare.

In the example above I declared variable test and initialized it with integer 1. As an output I got 0.

According to Grails Docs I can use scope attribute, and it solves the problem when set to request.

Are there any ways I can fix it otherwise? Why this happens?

NB: The inside of mk:pageViewTag is huge so I cannot just declare a variable anywhere outside.

Upvotes: 2

Views: 1486

Answers (4)

sandhya murugesan
sandhya murugesan

Reputation: 114

I declared a grails variable inside a template and used it in the parent gsp file (where the template is included).

Ex: Parent.gsp includes template: _child.gsp which has "<g:set var="a" value="${1}" />". Printing the variable 'a' in Parent.gsp renders a "null".

Hence we found that while inserting templates with variables or set variables while rendering a template doesn't work. Because rendering a template takes time and is async with the Parent page.We can't be sure of the variable initialization until the rendering is completed.

If the scope is set to "request",then we say that this variable should be visible for the whole request cycle and they are stored in the request for further process or access. Using <g:set var="a" value="${1}" scope='request'/> or <g:set var="a" value="${1}" scope='session'/>is recommended.

Refer these links of how to use scopes:

grails scope questions - page, request, flash

How to use grails <g:set> tag session scope?

Upvotes: 0

Pablo Pazos
Pablo Pazos

Reputation: 3216

g:set needs a var attribute not a name: http://grails.org/doc/2.2.1/ref/Tags/set.html

Upvotes: 1

jenk
jenk

Reputation: 1043

string namespace = "mk"

def pageViewTag = { attrs, body ->
  out << render(template: '/templates/pageTagView', model:[body: body()])
}

templates/_pageTagView.gsp :

<body>
  ${body}
  ...
</body>

Upvotes: 0

MiKo
MiKo

Reputation: 2146

Not perfect, but quick solution that does not require tricks (well, almost).
I execute body first and then I include it as template body.

Taglib (UtilTagLib.groovy):

string namespace = "mk"

def pageViewTag = { attrs, body ->

    // Render body ahead!
    String renderedBody = body()

    out << render(template: '/templates/pageTagView') {
        renderedBody
    }
}
...

Upvotes: 1

Related Questions