6

I don't know if the following change is an issue or it is intended.

<g:include view="line.gsp" params="['label':'test', 'progress':false]"/>

Then the expression in line.gsp aways evaluates to true, because the type of the 'progress' param is String, not Boolean.

  class is: ${params.progress.getClass()}
  <g:if test="${params.progress}">
   this should not be displayed
 </g:if>

Note that the same is applicable for other types, not just Boolean. I am using grails 3.3.8 This didn't happen in grails 2.5.2.

I didn't find anything about this online so that's why I am asking here. Thanks.

Edit:

As suggested by Daniel, I've tried with grails 3.3.2 also. I just created an app with grails create-app and modified the existing index.gsp to include line.gsp, as shown in the code above.

Here is a screenshot: enter image description here

Gabi
  • 687
  • 1
  • 7
  • 18
  • This is working as expected in grails 3.3.2 at least. I just tested your exact example and `${params.progress.getClass()}` was Boolean, and it evaluated properly in an if block. Perhaps something else is going on? Any chance you're already passing a `progress` param into the parent view? – Daniel Jan 10 '19 at 16:59
  • Hmm, I've tried with 3.3.8, 3.0.0 and grails 2.5.2. I created the apps from scratch with grails create-app. I just created a simple line.gsp file containing the code from the question and then modified the existing index.gsp file to include the line.gsp file. I didn't do any other change. Weird. – Gabi Jan 10 '19 at 20:02
  • What happens if you output `${params.progress}` in your line.gsp? Or `${params.progress.getClass()}`? – Daniel Jan 10 '19 at 20:02
  • it shows true for both grails 2 and 3, but it shows java.lang.String() for grails 3 while for grails 2 it is java.lang.Boolean. That's how I noticed that progress is interpreted as a String, because initially I had a different error in the gsp that was actually caused by this. I will try it with grails 3.3.2 also. Thanks. – Gabi Jan 10 '19 at 20:26
  • @Daniel I've tried with grails 3.3.2 also, even on a different system, and I get the same results. I eddited my question with a screenshot. – Gabi Jan 10 '19 at 20:51
  • Worth just looking at the code in `org.grails.plugins.web.taglib.UrlMappingTagLib` for the include closure, it may be obvious, or not – Mike W Jan 14 '19 at 15:28
  • Yeah, I did. I ended up using – Gabi Jan 14 '19 at 21:14
  • Note that you can `g:include` a view with a `model` as well. – Daniel Jan 16 '19 at 00:13

3 Answers3

0

Yes, this is true. When you are calling params.something, you are actually accessing GrailsParameterMap which is a Map. So your condition actually evaluates as Map->get() which will be Object->toString() and of course it is true cause it's not null and not empty. So the solution will be the following:

<g:if test="${params.getBoolean("progress")}">
   this should not be displayed
</g:if>
Mamun Sardar
  • 2,679
  • 4
  • 36
  • 44
  • Yeah, I noticed that. My only concern was how come this was changed in grails 3. – Gabi Jan 13 '19 at 13:09
  • Why do you believe that GrailsParameterMap necessarily returns a String value? – Daniel Jan 15 '19 at 22:29
  • I mention in this condition only. You can check by: ${params.progress?.getClass()} which will print: class java.lang.String. Yes: the GrailsParameterMap can store diff type of Object in value on other scenarios as always. – Mamun Sardar Jan 16 '19 at 09:41
0

You can test this as follows

<g:if test="${params.progress && params.progress == 'false'}">
   this should not be displayed
 </g:if>
elixir
  • 1,394
  • 1
  • 11
  • 21
  • Yeah, I noticed that. My only concern was how come this was changed in grails 3. Migrating an app from grails 2 to grails 3 involves changing all such occurrences that previusly worked in grails 2. – Gabi Jan 13 '19 at 13:10
0

I realize you have already found a workaround to this, but it was bothering me that your code was not working the same way mine was, so I decided to investigate a bit further in case anyone else runs into this issue.

As other people here have mentioned, params.anything will typically return a String value. This is because params are typically encoded as URI parameters (like ?progress=false) and not autoboxed into any other type. (This is perfectly reasonable; there would be no good way for Grails to know what type they should be.) However, it is possible (and occasionally reasonable) to render your view or template from a controller like render view: whatever, model: [your: model, params: params] where you specifically include params in the model. (Perhaps you have a lot of parameters that you do not need to individually recreate in the model.) In this case, the params map will exist as both URI parameters (?progress=false) and page-scoped model entry (params: [progress: Boolean.FALSE]). Page scope takes priority over URI parameters, and so your types will be preserved.

In my testing, I added your code to an existing page where I was already passing params into the model, and so type was preserved for a newly added parameter as well. (Note that once params are in page scope, they're there for included templates or views as well.) Consequently, I saw progress type of Boolean, while in a basic example it would be type String.

TL/DR: either assume params are strings, or explicitly include params in your page-scoped model when rendering.

Daniel
  • 3,312
  • 1
  • 14
  • 31