Grails Tag Not Resolving Variables in Its Body
I think I'm having a little difficulty with when variables are parsed in grails tags.
In my tag library, I have
def contentArea = {attrs, body ->
def domainObject = Class.forName("${attrs.contentType}", true, Thread.currentThread().contextClassLoader).newInstance()
def numberOfRows = !StringUtils.equals("${attrs.max}", "null")? new Integer("${attrs.max}") : new Integer("1");
def results = domainObject.getByContentAreaKey("${attrs.contentAreaKey}", numberOfRows)
out << g.render(
template: '/layouts/contentTag',
model: [contentAreaKey: attrs.contentAreaKey, results : results, contentNamespace: "${attrs.contentAreaKey}" + "_contentList", body:body()])
out << body()
}
in _contentTag.gsp, the layout is:
<b>In tag layout, </b>
<g:set var="${contentNamespace}" value="bobby"/>
contentNamespace = ${contentNamespace}<br/><!-- prints "minicontent_contentList" -->
minicontent_contentList = ${minicontent_contentList}<br/> <!-- prints "bobby" -->
And in the calling gsp, the tag is called:
<mynamespace:contentArea var="myVar" contentAreaKey="minicontent" contentType="com.my.test.Min开发者_JS百科iContentType">
<br/>Test Text<br/>
<b>in calling GSP,</b>
contentNamespace = ${contentNamespace}<br/><!-- prints nothing -->
minicontent_contentList = ${minicontent_contentList}<br/><!-- prints nothing -->
</mynamespace:contentArea>
contentNamespace and minicontent_contentList are not resolved in the body of the tag. Is it possible for the variables to be resolved? If so, how should I do it?
In case it helps with the answer, I have a page with a number of small content areas that I want to be able to administer via a different controller. The content areas all have similar data behind them (text, link, graphic, etc), but the layouts will be different. I have used sitemesh layouts to block out the page, and the calling gsp represents one of those sitemesh content blocks.
I am very new to grails and to asking for help on SO, so I am perfectly willing to take criticism, but please be gentle. :)
The body
, as passed in parameter, is a Closure
, which will resolve its methods and parameters to the location where it was declared, which here will be the main gsp. You could try setting the delegate
of the body
to the tag library and set the resolveStrategy
to Closure.DELEGATE_FIRST
. This should allow you to resolve contentNamespace
.
def contentArea = {attrs, body ->
...
def contentNamespace = "${attrs.contentAreaKey}" + "_contentList"
out << g.render(
...
body.delegate = this
body.resolveStrategy = Closure.DELEGATE_FIRST
out << body()
}
To resolve minicontent_contentlist
would be harder as I'm not sure how to specify the template as the delegate. You could try defining the variable in the tag tibrary and passing it in to the template model, then you assign the minicontent_contentlist
value to that passed object, which may update the value back in the tag library code for the resolveStrategy
to work, assuming it is the same object passed by reference.
def contentArea = {attrs, body ->
...
def minicontent_contentList
out << g.render( ..., model:[minicontent_contentList:minicontent_contentList])
...delegate and resolveStrategy stuff...
}
<b>In tag layout, </b>
<g:set var="minicontent_contentlist" value="bobby"/>
contentNamespace = ${contentNamespace}<br/><!-- prints "minicontent_contentList" -->
minicontent_contentList = ${minicontent_contentList}<br/> <!-- prints "bobby" -->
As a final option you could try assigning the delegate/resolveStrategy
inside gsp curlies (${}
) in the template to see if that assigns the template object to the delegate
parameter.
精彩评论