开发者

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.

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜