在Grails中,通过g:set将taglib返回值传递到视图中



我正在使用grail2.3.3,我正在尝试为自定义tagLib的返回值分配一个HTML值。我尝试了许多方法,但没有成功。

正在发生的事情是网页上显示了正确的输出(因此 tagLib 的逻辑没问题),但我需要的单个值没有传递给 to 'var' organId。

查看了之前的各种帖子后,以下是到目前为止我在查看 gsp 文件中感到厌倦的事情:

<g:returnLoginInfo loginId="${loginId}" fieldName="organId">
<g:set var="organId" value="${0}" scope="flash" />
</g:returnLoginInfo>

我还尝试了 value="${it}" 作为引用从 tagLib 传递的值的默认 it 参数。在 tagLib 中,我尝试通过"out <<"返回单个值,以及尝试在添加行后返回:

static returnObjectForTags = ['returnLoginInfo'] 

这确保了 tagLib 可以返回值,而不是直接发送文本

。视图 gsp 文件中的另一种方法是:

<g:set var="organId" value="${bind.returnLoginInfo(loginId="${loginId}" fieldName="organId")}"/>

我欢迎任何建议。

这是标签库:

package homevu1
class ReturnLoginInfoTagLib {
//static defaultEncodeAs = 'html'
static defaultEncodeAs = [taglib:'html']
//static encodeAsForTags = [tagName: 'raw']
//static returnObjectForTags = ['returnLoginInfo'] // now expects a return statement rather than an out at the end
def returnLoginInfo = {attrs, body->
def loginId = attrs["loginId"]
def fieldName= attrs["fieldName"]
def tagName = "returnLoginInfo"
log.debug(" $tagName START loginId: $loginId fieldName: $fieldName")
def secUserInstance = SecUser.get(loginId)
log.debug(" $tagName secUser: $secUserInstance")
log.debug(" $tagName secUser id: $secUserInstance.id")
log.debug(" $tagName secUser role: $secUserInstance.role")
log.debug(" $tagName secUser organId: $secUserInstance.organId")
def returnValue
if (fieldName == "organId")
{
def organisationInstance= OrganisationShr.findByName(secUserInstance.organId)
returnValue = organisationInstance.id   
}

log.debug(" $tagName returnValue: $returnValue")
//return returnValue
out << body(returnValue)
} // end returnLoginInfo

正如下面的 Jacob 所建议的,我尝试了两种从视图中调用此 tagLib 的方法:

<g:set var="organId" value="${g.returnLoginInfo(loginId:"${loginId}", fieldName:"organId")}" />

<g:returnLoginInfo loginId="${loginId}" fieldName="organId">
<g:set var="organId" value="${it}" />
</g:returnLoginInfo>

不太确定我应该如何为第一种方法编码 return 语句?

使用过滤器 - 更新 2:

这是服务(不确定我的返回值语法是否正确):

package homevu1
class HvLoginDetailsService {
def springSecurityService
def myLoginDetails() {
def serviceName = "myLoginDetails"
def returnValue = 0
log.debug(" $serviceName hello world: $returnValue")
return 'hello'
} // end returnLoginInfo
} // HvLoginDetailsService

下面是筛选器定义:

package homevu1
class HomeVuFiltersController {
def HvLoginDetailsService
def filters = {
loginFilters(controller:'*', action:'*') {
before = {
}
after = { Map model ->
model.currentLoginDetails = HvLoginDetailsService.myLoginDetails()
}
}
}
} //eof controller

最后,我在 html 网页中调用它:

通过过滤器:

<p> ${currentLoginDetails}</p>

这显示了页面,但无法显示此返回值"hello" - 我相信这是因为它无法解析过滤器,并且只是假设当前登录详细信息是 html 中未定义的值。

或直接从服务:

<p> ${grailsApplication.mainContext.getBean("hvLoginDetailsService").myLoginDetails()}</p>

此操作失败并显示错误:

没有定义名为"HvLoginDetailsService"的 bean

问候

话筒

如果你只需要从 taglib 中设置一个值(使用 Grails 2.5.0 测试),你必须让你的 TagLib 使用 out 变量,如下所示:

class DemoTagLib {
static defaultEncodeAs = [taglib:'html']
def stackOverflowExample = { attrs ->
out << "This is your value ${attrs.value}"
}
}

你可以在你的 gsp 中像这样使用它(两种方式都有效)

<g:set var="organId" value="${g.stackOverflowExample(value:'Hello Grails')}" />
<h1>organId = ${organId}</h1>
<h1>organId2 = ${g.stackOverflowExample(value:'Hi Grails')}</h1>

要让它像在你的第一个例子中一样工作,你可以按照这样的思路做一些事情,在你的 taglib 中引用 body 参数:

def anotherExample = { attrs, body ->
out << body('My new return value')
}

并在 GSP 中使用它:

<g:anotherExample>
<g:set var="myVariable" value="${it}" />
<h2>Hey: ${myVariable}</h2>
</g:anotherExample>

更新:

您的标签库定义为:

def returnLoginInfo = {attrs, body->
def loginId = attrs["loginId"]
def fieldName= attrs["fieldName"]
def tagName = "returnLoginInfo"
log.debug(" $tagName START loginId: $loginId fieldName: $fieldName")
/*
def secUserInstance = SecUser.get(loginId)
log.debug(" $tagName secUser: $secUserInstance")
log.debug(" $tagName secUser id: $secUserInstance.id")
log.debug(" $tagName secUser role: $secUserInstance.role")
log.debug(" $tagName secUser organId: $secUserInstance.organId")
*/
def returnValue = 10
if (fieldName == "organId")
{
//            def organisationInstance= OrganisationShr.findByName(secUserInstance.organId)
returnValue = 20 //organisationInstance.id
}

log.debug(" $tagName returnValue: $returnValue")
//return returnValue
out << body(returnValue)
} // end returnLoginInfo

视图中的以下代码有效:

<g:returnLoginInfo loginId="${loginId}" fieldName="organId">
<g:set var="organId" value="${it}" />
</g:returnLoginInfo>
<h3>As taglib: organId = ${organId}</h3>
<g:returnLoginInfo loginId="${loginId}" fieldName="notOrganId">
<g:set var="organId" value="${it}" />
</g:returnLoginInfo>
<h3>As taglib: organId = ${organId}</h3>

为我提供 organId 的输出 20 和 10。

话虽如此,我不确定我是否会为您的用例使用 TagLib,我会使用服务,并通过控制器提供给视图的地图提供值。

更新 2:

以上内容已通过Grails 2.5.0进行验证。您的用例不像 TagLib 用例那样接缝,而您只想设置一个值。我会走向不同的方向。如果您不需要参数(因为它们可能来自会话或安全服务),过滤器将完成这项工作。

逻辑的服务可以是这样的:

@Transactional
class DemoService {
List<Integer> myServiceMethod(Integer i) {
if( i > 0) {
(1..i).collect { it }
} else {
[i]
}
}
}

你可以做一个这样的过滤器:

class MyFilterFilters {
DemoService demoService
def filters = {
all(controller:'*', action:'*') {
before = {
}
after = { Map model ->
model.myIdValue = demoService.myServiceMethod(5)
}
afterView = { Exception e ->
}
}
}
}

您可以直接在每个视图中访问 myIdValue:

<p> ${myIdValue}</p>

如果需要参数,可以直接从视图中使用服务(不推荐 - 但可能,并且不会比从 taglib 使用它对性能的影响更大):

<p> ${grailsApplication.mainContext.getBean("demoService").myServiceMethod(3)}</p>

最新更新