Thymeleaf Error for <input> date with th:pattern - java

I'm trying to use th:pattern for date input form field like following for a thymeleaf template using spring-mvc but without luck. Anybody else experienced similar thing and has some insight or alternative?
I tried 1. hard-coding the pattern
<input type="text" th:pattern="MM/dd/yyyy" th:field="*{classDate}"/>
received Error:
Request processing failed; nested exception is org.thymeleaf.exceptions.TemplateProcessingException: Could not parse as expression: "MM/dd/yyyy"
And 2. setting pattern in java code for template to use
<input type="date" th:pattern="${classdate_format}" th:field="*{classDate}"/>
received Error:
Request processing failed; nested exception is org.thymeleaf.exceptions.TemplateProcessingException: Error during execution of processor 'org.thymeleaf.spring3.processor.attr.SpringInputGeneralFieldAttrProcessor'

pattern is html5 attribute of input tag.
pattern validates an input value using regex. So that value, which you inserts into pattern attribute should be correct regex pattern.
If you are using Thymeleaf's th: prefix, template processor trying to find appropriate variable in Spiring's model and insert it as a value of attribute. Thymeleaf is using Spring EL for it's templates.
So your first approach is incorrect because of using invalid SpringEL expression.
The second solution looks better, type="date" gives you exactly what you want, but works not for all browsers. ${classdate_format} looks like correct expression. To understand what causes the second error more code needed.
Anyway is there any reason to use th: prefix for pattern attribute? It needed only if you want to create regex pattern dynamically at server side. But in this case regex pattern is pretty straightforward, so you can use attribute without th:. To write correct regex for your case please refer to this answer.

Related

Thymeleaf template and Spring Boot : Creating a radio input from Java enum

I would like to populate a radio input control in a Thymeleaf automatically from a Java enum type called "source". I am using Spring Boot in the backend.
My controller initialises a list of the enum values like this:
this.sourcesAsList = Arrays.asList(Source.values());
model.addAttribute("sources", sourcesAsList);
This works fine, at least as far as the List is concerned (as I can see in the log output).
The Thymeleaf template then tries to instantiate a radio control based on this attribute in the model, like so:
<div th:each="source : ${sources}">
<input type="radio" th:field="*{source}" th:value="${source.value}"/><label th:text="| ${source.value} |">Should not see this !</label>
</div>
However, when I try to load this page, I get the following error:
[Request processing failed; nested exception is org.thymeleaf.exceptions.TemplateInputException: An error happened during template parsing (template: "class path resource [templates/feedbackapp2.html]")] with root cause
java.lang.IllegalStateException: Neither BindingResult nor plain target object for bean name 'source' available as request attribute
The enum is pretty simple:
public enum Source {
VALONE, VALTWO, VALTHREE, VALFOUR;
public String getName() {
return this.name();
}
}
It's the first time I work with Thymeleaf, so I guess it is just a simple syntax problem somewhere, but even after googling I couldn't find a working example. Any ideas? Is it possible at all to do this with an enum? If not, what kind of datatype would be more appropriate?
Thanks a lot.
Cheers,
Martin
I played around a bit more and got it working. The following HTML snippet displays the radio buttons correctly based the list of Enums and also is wired to the model correctly, in that I received the selected value in the controller's POST method:
<div th:each="source : ${sources}">
<input name="source" type="radio" th:value="${source}"/><label for="source" th:text="| ${source} |">Something is wrong !</label>
</div>
There were two problems:
it is not necessary to access the name() attribute of the enum (so,
using ${source} instead of ${source.name} is fine)
instead of th:field, use the namne attribute of the input control
Thanks a lot to Periklis for the comment.

Thymeleaf Map<String, Object> iteration and non-english chars in map key

I have Spring, Thymeleaf, HTML5 web page. And have problem iterating through Map if map object contains non-english characters.
All the character encoding filters/resolvers/converters are set and forced to UTF-8
Let's say I have the following setup:
Controller:
#RequestMapping(value = "/app", method = { RequestMethod.GET, RequestMethod.POST })
public String view(ModelMap model, #RequestParam(value = "foo", required = false) Integer foo) {
MapDTO mapDto = new MapDTO();
Map<String, List<Foo>> mapFoo ... // populate map etc.
model.add("mapDto", mapDto.setMapFoo(mapFoo))
return foo == null ? VIEW : VIEW + " :: fooFragment"
}
And template for testing purposes:
.. page ..
<div th:fragment="fooFragment" id="fooFragment">
..
<th:block th:each="fooMap : ${mapDto.mapFoo}">
<th:block th:each="item,row : ${fooMap.value.fooList}">
<p th:text="${item.val}"</p> <!-- working OK -->
<p th:text=" ${fooMap.value.fooList[__${row.index}__].idrValueName} "></p> <!-- working OK -->
<input th:field="*{mapDto.mapFoo[__${fooMap.key}__].fooList[__${row.index}__].val} "></p><!-- And this is working -->
<p th:text="${mapDto.mapFoo[__${fooMap.key}__].fooList[__${row.index}__].val} "></p><!-- FAILING ON THIS -->
</th:block>
</th:block>
..
</div>
.. rest of the page ..
Let's say, that i have map with keys "A" and "Ā".
I'm getting following exception:
org.springframework.web.util.NestedServletException: Request processing failed; nested exception is org.thymeleaf.exceptions.TemplateProcessingException: Exception evaluating SpringEL expression: "mapDto.mapFoo[Ā].fooList[0].val"
..
Caused by:
java.lang.IllegalStateException: Cannot handle (257) 'Ā'
Whats interesting - I have almost exactly the same setup on different page (A bit different mapDto structure and template, but the same principle, same page headers) and I don't have the same issues there.
Maps that don't have keys with non-english characters behaves as predicted.
Any ideas where lies the problem?
SOLVED:
Solved described issue using double-bracket syntax
${{...}}
There are some limitations with it. But I was able to work around them it solved my main issue.
mapDto.mapFoo[Ā].fooList[0].val
This expression contains accented character Ā. Looking at the source code of Tokenizer, accented characters are clearly indicated as an invalid candidate for tokenization.
Spring EL's InternalSpelExpressionParser which is responsible for parsing expressions is tightly coupled to this Tokenizer, so I don't think there is an out of the box way to allow tokenization of accented characters. I'm pretty sure there is a good reason why this is not allowed (e.g. it might break other parts of the framework) so I suggest you go along to what the framework is demanding and remove the accented characters in the expression.

thymeleaf - combined th:each with th:href

I'm new to Thymeleaf (and webdev) and I'm trying to combine Thymeleaf iteration (th:each) with URL re-writing (th:href).
<a th:each="lid : ${lists}" th:text="${lid}" th:href="#{/list?l=${lid}}">
hello
</a>
This produces the following (where lid=45):
45
So, it did the substitution on the th:text, but not on the th:href.
I'm not trying to do any sort of URL re-writing, I'm just using the '#' syntax because I want Thymeleaf to substitute the 'lid' attribute.
I'm using the current version of Thymeleaf (2.1.2) with Google App Engine.
If you don't want to do any url rewriting, you shouldn't use the # syntax.
You can use the pipeline (|) syntax to do some literal substitions:
th:href="|/list?l=${lid}|"
Source: Thymeleaf documentation
You can also try this way:
<a th:href="#{'/list?l=' + ${lid}}" th:text="${lid}">element</a>
I don't have enough reputation to add a comment on a previous post but the Thymeleaf Source documentation link from a previous post is broken. Documentation can now be found at the following link:
Thymeleaf Standard URL Syntax
Section 9 Using Expressions in URLs in this documentation explains how you can use expressions within other expressions when generating URLs with the # syntax. The following is an example:
<a th:href="#{/order/details(id=${modelattribute})}"/>
Will produce a link similar to:
http://domain.org/context/order/details?id=1
if modelattribute had a value of 1 in the current context.

Parse Jsp file and find specific tags using Java

I need a way to find specific tags in my class.
Example code :
<ace:column id="test1"></ace:column>
<ace:column id="test2"></ace:column>
<ice:panelGrid id="test3" columns="4" />
Now I want to process the file with above contents ,parse it and get all the tag values with identifier "id".
I would expect to get
test1
test2
test3
Thanks.
Use parsers. There are a lot of and for the tutorial on how to parse see this URL.
If you need to process the tags themselves, you would need to rely on some parser such as JSoup.
That being said, if all you want are the values following the id string, you could rely on regular expressions, somthing such as: id="([^"]*?)".

Problem with JSP EL evaluation

Why doesn't the following work:
<c:set var="formId" value="#${otherFormId}"/>
where
<c:set var="formId" value="# ${otherFormId}"/>
notice the space ^
works fine (though is invalid for my purposes). Im trying to prepend ${otherFormId} with a # symbol (i.e. creating jquery id selector).
The first form ends up with
#${otherFormId}
literally in the output. How can I get the outcome I am after?
Got the answer.
#{expr}
is an expression whose evaluation is deferred (something to do with JSF lifecycle requirements) and was introduced as part of the Unified EL. To get around my problem you now need to escape any literal #'s. e.g.
<c:set var="formId" value="\#${otherFormId}"/>

Categories

Resources