包含 g:include 的布尔参数作为字符串传递给包含的视图
Include boolean params with g:include are passed as Strings to the included view
我不知道以下更改是一个问题还是有意为之。
<g:include view="line.gsp" params="['label':'test', 'progress':false]"/>
然后 line.gsp 中的表达式计算结果为真,因为 'progress' 参数的类型是字符串,而不是布尔值。
class is: ${params.progress.getClass()}
<g:if test="${params.progress}">
this should not be displayed
</g:if>
请注意,这同样适用于其他类型,而不仅仅是布尔值。
我正在使用 grails 3.3.8
这在 grails 2.5.2 中没有发生。
我在网上没有找到任何相关信息,所以我才来这里问。谢谢
编辑:
按照丹尼尔的建议,我也尝试过使用 grails 3.3.2。
我刚刚使用 grails create-app 创建了一个应用程序,并修改了现有的 index.gsp 以包含 line.gsp,如上面的代码所示。
截图如下:
是的,这是真的。当您调用 params.something
时,您实际上是在访问 GrailsParameterMap,它是一个 Map。所以你的条件实际上评估为 Map->get() 它将是 Object->toString() 当然它是真的因为它不是 null 也不是空的。所以解决方案如下:
<g:if test="${params.getBoolean("progress")}">
this should not be displayed
</g:if>
您可以按如下方式进行测试
<g:if test="${params.progress && params.progress == 'false'}">
this should not be displayed
</g:if>
我知道您已经找到了解决方法,但令我困扰的是您的代码与我的代码运行方式不同,因此我决定进一步调查以防其他人遇到此问题。
正如这里的其他人所提到的,params.anything
通常会 return 一个字符串值。这是因为参数通常被编码为 URI 参数(如 ?progress=false),而不是自动装箱为任何其他类型。 (这是完全合理的;Grails 没有什么好的方法可以知道它们应该是什么类型。)但是,可以(有时是合理的)从控制器呈现您的视图或模板,例如 render view: whatever, model: [your: model, params: params]
特别是在模型中包含参数。 (也许你有很多不需要在模型中单独重新创建的参数。)在这种情况下,params 映射将作为 URI 参数 (?progress=false) 和页面范围的模型条目 (params: [进度:Boolean.FALSE])。页面范围优先于 URI 参数,因此您的类型将被保留。
在我的测试中,我将您的代码添加到我已经将参数传递到模型的现有页面,因此也为新添加的参数保留了类型。 (请注意,一旦参数在页面范围内,它们也适用于包含的模板或视图。)因此,我看到了 Boolean 类型的进度,而在基本示例中它将是 String 类型。
TL/DR:假设参数是字符串,或者在渲染时在页面范围模型中明确包含参数。
我不知道以下更改是一个问题还是有意为之。
<g:include view="line.gsp" params="['label':'test', 'progress':false]"/>
然后 line.gsp 中的表达式计算结果为真,因为 'progress' 参数的类型是字符串,而不是布尔值。
class is: ${params.progress.getClass()}
<g:if test="${params.progress}">
this should not be displayed
</g:if>
请注意,这同样适用于其他类型,而不仅仅是布尔值。 我正在使用 grails 3.3.8 这在 grails 2.5.2 中没有发生。
我在网上没有找到任何相关信息,所以我才来这里问。谢谢
编辑:
按照丹尼尔的建议,我也尝试过使用 grails 3.3.2。 我刚刚使用 grails create-app 创建了一个应用程序,并修改了现有的 index.gsp 以包含 line.gsp,如上面的代码所示。
截图如下:
是的,这是真的。当您调用 params.something
时,您实际上是在访问 GrailsParameterMap,它是一个 Map。所以你的条件实际上评估为 Map->get() 它将是 Object->toString() 当然它是真的因为它不是 null 也不是空的。所以解决方案如下:
<g:if test="${params.getBoolean("progress")}">
this should not be displayed
</g:if>
您可以按如下方式进行测试
<g:if test="${params.progress && params.progress == 'false'}">
this should not be displayed
</g:if>
我知道您已经找到了解决方法,但令我困扰的是您的代码与我的代码运行方式不同,因此我决定进一步调查以防其他人遇到此问题。
正如这里的其他人所提到的,params.anything
通常会 return 一个字符串值。这是因为参数通常被编码为 URI 参数(如 ?progress=false),而不是自动装箱为任何其他类型。 (这是完全合理的;Grails 没有什么好的方法可以知道它们应该是什么类型。)但是,可以(有时是合理的)从控制器呈现您的视图或模板,例如 render view: whatever, model: [your: model, params: params]
特别是在模型中包含参数。 (也许你有很多不需要在模型中单独重新创建的参数。)在这种情况下,params 映射将作为 URI 参数 (?progress=false) 和页面范围的模型条目 (params: [进度:Boolean.FALSE])。页面范围优先于 URI 参数,因此您的类型将被保留。
在我的测试中,我将您的代码添加到我已经将参数传递到模型的现有页面,因此也为新添加的参数保留了类型。 (请注意,一旦参数在页面范围内,它们也适用于包含的模板或视图。)因此,我看到了 Boolean 类型的进度,而在基本示例中它将是 String 类型。
TL/DR:假设参数是字符串,或者在渲染时在页面范围模型中明确包含参数。