In Thymeleaf, when binding failure by absence of a property,
the property is replaced with empty string.
How to make Thymeleaf fail to render in the case?
UPDATE:
This is a sample project I'm working on:
https://github.com/izeye/samples-spring-boot-branches/tree/thymeleaf
When I run the HomeControllerTests.test(),
I expect I've got an exception
because I did not provide the age property in the model.
But it's rendered with an empty string.
I agree it's a nice behavior in general
but in my current situation,
I hope to be certain that there's no missing property when rendering.
Related
I've seen a lot of answers about how to send PUT/DELETE/PATCH HTTP requests with thymeleaf, and it's by using th:method = "the_specific_method", but i haven't found the thymeleaf specification about that. Can anyone help showing me where is it?
Thanks in advance.
I've tried to google for the answer, but no luck.
th:method isn't special to Thymeleaf -- it's just like any other plain old attribute which will output the result of an expression to the method attribute. It doesn't do (or care about) anything else. You can put any string and/or string expression into it, and Thymeleaf will happily output it.
th:method="${'the_specific_method'}"
will output
method="the_specific_method"
without regards to whether or not it's valid. If you want to learn about the method attribute, you just need to learn about how method works in plain old regular html and how browsers (and/or Spring) work with it.
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:
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.
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>
You can test this as follows
<g:if test="${params.progress && params.progress == 'false'}">
this should not be displayed
</g:if>
Is there a way to conditionally include strings in a Serilog template?
For example,
_logger.Information("Event: {evt} Description: {dsc}", evt, dsc}
How do I omit the "Description:" string if dsc is null or empty?
The message template is definitely a fixed point in the equation.
If the description is an ancillary field for you, you could do
_logger.ForContext("Description",dsc).Information("Event: {evt}", evt}
... if you do this, be sure to include {Properties} in log rendering format string to include context fields such as this which are not used in the actual message template.
Other than that, you're left with a humble if:
if(desc!=null)
_logger.Information("Event: {evt} Description: {dsc}", evt, dsc}
else
_logger.Information("Event: {evt}", evt);
Note, this will yield a different message template id in the message under the hood for obvious reasons, which may be a reason to prefer the former.
(Also not possible is the ternary operator instead of if - that will run you into trouble with the Serilog Analyzer)
I came across some .xhtml files where for some components the expression language used was like rendered="#{empty from}", rendered="#{empty create}" etc.
I know that empty is an operator in EL, used to check whether a value is null or empty, but I did not understand the meaning of above mentioned ELs.
Can somebody explain to me what above EL's mean?
The rendered attribute is a signal whether JSF should generate HTML for the component or not. If it evaluates false, then it won't generate HTML for the component (nor for its children). The #{empty form} will evaluate false when the #{form} is not null nor empty.
Simple as that. You can find another examples of boolean expressions here: Conditionally displaying JSF components
I have hashmap that was created on a page using the struts2 <s:set> tag. It looks something like this
<s:set var="mymap" value="#request.mymap"/>
At some point in the page, i need to get a value from the hashmap based upon a key, and i want to do it using OGNL.
The key is generated based upon some logic, which i store using another <s:set> tag. Something like this
<s:set var="mykey" value="1">
I need to get a value from the hashmap using this key. And I need to display it.
How do I simply call the get function on the hashmap?
I tried this
<s:property value="#mymap[#mykey]"/>
and this
<s:property value="#mymap[%{#mykey}]"/>
and this
<s:property value="%{#mymap[%{#mykey}}]"/>
The third one obviously does not work because of the nesting problem.
But the same nesting logic is applicable to the second case as well, due to the manner the value attribute is handled. However none seem to work for me.
The issue here is that my key is unknown. It is a dynamically generated string based upon some pattern. I need to access the object stored in the hashmap using this dynamic key. And due to the inability of nesting ognl, I am in a fix.
I suppose the issue is very simple. I almost feel that I get it, but somehow the solution eludes me.
I suppose I was using a different version of struts wherein using the %{} was required for the expression to be evaluated. I changed the jar files now.
This is what did the job for me:
<s:property value="#mymap.[#mykey2]"/>
My problem was coming because I was trying to use it in a href for a s:a tag. And without the %{} operator, the expression was not being evaluated.
So, i guess, i was right in the beginning itself. Rest of the time, it was just me being silly. :>
Update:
I wrote a blog post on the issue, in case anyone is interested.
http://mycodefixes.blogspot.com/2010/11/struts-2-creating-and-accessing-maps.html