First partThe second part of7 Check and error messages
Most of our forms should display validation messages to inform the user about errors he made.
Thymeleaf offers several tools for this: several functions in the
#fields object, attributes to
th: errors and
th: errorclass .
7.1 Field errors
Let's see how we can set a specific CSS class for a field if it contains an error:
<input type="text" th:field="*{datePlanted}" th:class="${#fields.hasErrors('datePlanted')}? fieldError" />
As you can see, the
# fields.hasErrors (...) function takes a field expression as a parameter (
datePlanted ) and returns a Boolean value indicating whether there are any validation errors for this field.
We can also get all the errors for this field and repeat them:
<ul> <li th:each="err : ${#fields.errors('datePlanted')}" th:text="${err}" /> </ul>
Instead of iterating, we could also use
th: errors , a specialized attribute that creates a list with all the errors for the specified selector, separated by <br />:
<input type="text" th:field="*{datePlanted}" /> <p th:if="${#fields.hasErrors('datePlanted')}" th:errors="*{datePlanted}">Incorrect date</p>
Error-based CSS style simplification:
th: errorclassThe example we saw above, setting the CSS class for an input form, if there are errors in this field, is so common that Thymeleaf offers a special attribute for precise execution:
th: errorclass .
Applied to a form field tag (input, select, textarea ...), it will read the name of the field to be checked from any existing
name or
th: field attributes in the same tag, and then add the specified CSS class to the tag, if such a field has any related errors:
<input type="text" th:field="*{datePlanted}" class="small" th:errorclass="fieldError" />
If there are errors in
datePlanted , it will look like this:
<input type="text" id="datePlanted" name="datePlanted" value="2013-01-01" class="small fieldError" />
7.2 All errors
And what if we want to show all the errors in the form? We just need to request the methods
# fields.hasErrors (...) and
# fields.errors (...) with the constants '
* ' or '
all ' (which are equivalent):
<ul th:if="${#fields.hasErrors('*')}"> <li th:each="err : ${#fields.errors('*')}" th:text="${err}">Input is incorrect</li> </ul>
As in the examples above, we could get all the errors and iterate on them ...
<ul> <li th:each="err : ${#fields.errors('*')}" th:text="${err}" /> </ul>
... and also create a divided list:
<p th:if="${#fields.hasErrors('all')}" th:errors="*{all}">Incorrect date</p>
Finally, notice that
# fields.hasErrors ('*') is equivalent to
# fields.hasAnyErrors () , and
# fields.errors ('*') is equivalent to
# fields.allErrors () . Use the syntax you prefer:
<div th:if="${#fields.hasAnyErrors()}"> <p th:each="err : ${#fields.allErrors()}" th:text="${err}">...</p> </div>
7.3 Global Errors
There is a third type of error in the Spring form: global errors. These are errors that are not related to any particular fields in the form, but still exist.
Thymeleaf offers a
global constant to access these errors:
<ul th:if="${#fields.hasErrors('global')}"> <li th:each="err : ${#fields.errors('global')}" th:text="${err}">Input is incorrect</li> </ul>
<p th:if="${#fields.hasErrors('global')}" th:errors="*{global}">Incorrect date</p>
... a also equivalent helper methods
# fields.hasGlobalErrors () and
# fields.globalErrors () :
7.4 Mapping errors out of form
Form validation errors can also be displayed out of the form using variables (
$ {...} ) instead of expression expressions (
* {...} ) and the prefix of the name of the component that supports the form:
<div th:errors="${myForm}">...</div> <div th:errors="${myForm.date}">...</div> <div th:errors="${myForm.*}">...</div> <div th:if="${#fields.hasErrors('${myForm}')}">...</div> <div th:if="${#fields.hasErrors('${myForm.date}')}">...</div> <div th:if="${#fields.hasErrors('${myForm.*}')}">...</div> <form th:object="${myForm}"> ... </form>
7.5 Rich Error Objects
Thymeleaf offers the ability to retrieve form error information in the form of beans (instead of simple strings) with the attributes
fieldName (String),
message (String), and
global (boolean).
These errors can be obtained using the service method
# fields.detailedErrors () :
<ul> <li th:each="e : ${#fields.detailedErrors()}" th:class="${e.global}? globalerr : fielderr"> <span th:text="${e.global}? '*' : ${e.fieldName}">The field name</span> | <span th:text="${e.message}">The error message</span> </li> </ul>
8 This is still a prototype!
Our application is ready. But let's take another look at the .html page we created ...
One of the most enjoyable consequences of working with Thymeleaf is that after all these features that we added to our HTML, we can still use this HTML as a prototype (we say it is the
Natural Template ). Let's open
seedstartermng.html right in our browser, without launching our application:

Here it is! This is not a working application, this is not real data ... but this is a completely correct prototype composed of beautifully displayed HTML code.
9 The Conversion Service
9.1 Configuration
As explained earlier, Thymeleaf can use the Transformation Service registered in the context of the application. Our application configuration class, expanding Spring’s own
WebMvcConfigurerAdapter , will automatically register a conversion service that we can customize by adding the necessary formatting tools. Let's see what it looks like:
@Override public void addFormatters(final FormatterRegistry registry) { super.addFormatters(registry); registry.addFormatter(varietyFormatter()); registry.addFormatter(dateFormatter()); } @Bean public VarietyFormatter varietyFormatter() { return new VarietyFormatter(); } @Bean public DateFormatter dateFormatter() { return new DateFormatter(); }
9.2 Double bracket syntax
The conversion service can be easily applied to convert / format any object into a string. This is done using the expression in double brackets:
- For variable expressions: $ {{...}}
- For the expression of choice: * {{...}}
So, for example, given the Integer-to-String converter, which adds commas as the thousands separator, this is:
<p th:text="${val}">...</p> <p th:text="${{val}}">...</p>
... should lead to:
<p>1234567890</p> <p>1,234,567,890</p>
9.3 Forms Use
We saw earlier that each
th: field attribute will always apply a translation service, so this is:
<input type="text" th:field="*{datePlanted}" />
... is actually equivalent to:
<input type="text" th:field="*{{datePlanted}}" />
Note that according to the Spring requirement, this is the only scenario in which the mapping service is used in expressions using the single-bracket syntax.
9.4 #conversions transform object
The #conversions utility object allows you to manually start the conversion service where needed:
<p th:text="${'Val: ' + #conversions.convert(val,'String')}">...</p>
The syntax for this service object is:
- # conversions.convert (Object, Class) : converts an object into the specified class
- # conversions.convert (Object, String) : the same as above, but specifying the target class as a String (note that the java.lang package may be omitted)
10 Drawing Fragments of the Template Fragments Template (AJAX etc)
Thymeleaf offers the ability to visualize only part of a template as a result of its execution: a
fragment .
This can be a useful component engine tool. For example, it can be used on controllers that run on
AJAX calls, which can return page markup fragments that have already been loaded into the browser (to update the selection, turn on / off buttons ...).
Fragmentary rendering can be achieved using Thymeleaf fragment specifications: objects that implement the
org.thymeleaf.fragment.IFragmentSpec interface.
The most common of these implementations is
org.thymeleaf.standard.fragment.StandardDOMSelectorFragmentSpec , which allows you to specify a fragment using a DOM selector in exactly the same way as those used in
th: include or
th: replace .
10.1 Definition of fragments in a view bean
View beans are beans of the
org.thymeleaf.spring4.view.ThymeleafView class declared in the context of the application (
Bean annotation if you are using Java configuration). They allow you to specify fragments as follows:
@Bean(name="content-part") @Scope("prototype") public ThymeleafView someViewBean() { ThymeleafView view = new ThymeleafView("index");
Given the above definition of a bean component, if our controller returns a
content-part (the name of the above-mentioned bean component) ...
@RequestMapping("/showContentPart") public String showContentPart() { ... return "content-part"; }
... Thymeleaf will return only the
content fragment of the index template - the location of which is likely to be approximately the same as
/WEB-INF/templates/index.html , after applying the prefix and suffix. Thus, the result will be completely equivalent to the indication of
index :: content :
<!DOCTYPE html> <html> ... <body> ... <div th:fragment="content"> Only this div will be rendered! </div> ... </body> </html>
Also note that thanks to Thymeleaf's powerful markup selectors, we can select a fragment in a template without any
th: fragment attributes. Let's use the
id attribute, for example:
@Bean(name="content-part") @Scope("prototype") public ThymeleafView someViewBean() { ThymeleafView view = new ThymeleafView("index");
10.2 Definition of fragments in the return value of the controller
Instead of declaring
view beans , fragments can be defined from the controller using
fragment expressions . Just like in
th: insert or
th: replace attributes.
@RequestMapping("/showContentPart") public String showContentPart() { ... return "index :: content"; }
Of course, all the power of DOM selectors is available again, so we can select our snippet based on standard HTML attributes, such as
id = "content" :
@RequestMapping("/showContentPart") public String showContentPart() { ... return "index :: #content"; }
And we can also use parameters such as:
@RequestMapping("/showContentPart") public String showContentPart() { ... return "index :: #content ('myvalue')"; }
11 Advanced integration features
11.1 Integration with RequestDataValueProcessor
Thymeleaf easily integrates with Spring
RequestDataValueProcessor interface. This interface allows you to intercept link URLs, form URLs and form field values before they are written to the markup result, and also transparently add hidden form fields that include security features, such as: protection against CSRF (cross-site request forgery) .
The
RequestDataValueProcessor implementation can be easily configured in the context of the application. It must implement the
org.springframework.web.servlet.support.RequestDataValueProcessor interface and have the
requestDataValueProcessor as the name of the bean:
@Bean public RequestDataValueProcessor requestDataValueProcessor() { return new MyRequestDataValueProcessor(); }
... and Thymeleaf will use this as follows:
- th: href and th: src call RequestDataValueProcessor.processUrl (...) before rendering the URL
- th: action calls RequestDataValueProcessor.processAction (...) before rendering the action attribute of the form, and additionally it detects when this attribute is applied to the <form> tag, which in any case must be the only place, and in this case calls RequestDataValueProcessor.getExtraHiddenFields (... ) and adds the returned hidden fields immediately before the closing </ form> tag
- th: value calls RequestDataValueProcessor.processFormFieldValue (...) to draw the value to which it refers, unless there is no th: field in the same tag (in this case, th: field will take care of itself)
- th: field calls RequestDataValueProcessor.processFormFieldValue (...) to draw the value of the field to which it is applied (or the body of the tag, if it is <textarea>)
Note that there are very few scenarios in which you would need to explicitly implement RequestDataValueProcessor in your application. In most cases, this will be automatically used by security libraries that you use transparently, for example, for example, Spring Security's CSRF.11.1 Building URIs to Controllers
Starting with version 4.1,
Spring allows you to create links to annotated controllers directly from the views, without having to know the URIs to which these controllers are mapped.
In Thymeleaf, this can be achieved using the expression
# mvc.url (...) , which allows you to specify controller methods in capital letters of the controller class in which they are located, followed by the method name. This is equivalent to the user-defined
spring: mvcUrlx (...) function in JSP.
For example, for:
public class ExampleController { @RequestMapping("/data") public String getData(Model model) { ... return "template" } @RequestMapping("/data") public String getDataParam(@RequestParam String type) { ... return "template" } }
The following code will create method references:
<a th:href="${(#mvc.url('EC#getData')).build()}">Get Data Param</a> <a th:href="${(#mvc.url('EC#getDataParam').arg(0,'internal')).build()}">Get Data Param</a>
You can read about this mechanism at
http://docs.spring.io/spring-framework/docs/4.1.2.RELEASE/spring-framework-reference/html/mvc.html#mvc-links-to-controllers- from-views12 Spring WebFlow Integration
Thymeleaf + Spring integration packages include integration with Spring WebFlow (2.3+).
WebFlow includes some AJAX features for rendering fragments of the rendered page when certain events (transitions) are triggered, and in order for Thymeleaf to track these AJAX requests, we will need to use another ViewResolver implementation configured as:
<bean id="thymeleafViewResolver" class="org.thymeleaf.spring4.view.AjaxThymeleafViewResolver"> <property name="viewClass" value="org.thymeleaf.spring4.view.FlowAjaxThymeleafView" /> <property name="templateEngine" ref="templateEngine" /> </bean>
... and then this
ViewResolver can be configured in
WebFlow ViewFactoryCreator as:
<bean id="mvcViewFactoryCreator" class="org.springframework.webflow.mvc.builder.MvcViewFactoryCreator"> <property name="viewResolvers" ref="thymeleafViewResolver"/> </bean>
From here, you can define Thymeleaf templates in your view-state's:
<view-state id="detail" view="bookingDetail"> ... </view-state>
In the above example,
bookingDetail is a Thymeleaf template specified in the usual way, understandable to any of the template resolvers configured in TemplateEngine.
12.2 AJAX Fragments in Spring WebFlow
Please note that this only explains how to create AJAX fragments for use with Spring WebFlow. If you are not using WebFlow, creating a Spring MVC controller that responds to an AJAX request and returns a piece of HTML is as simple as creating any other controller that returns a template, with the only exception that you will probably return a snippet like " main :: admin "from your controller method.WebFlow allows you to define rendering via AJAX with <render> tags, like this:
<view-state id="detail" view="bookingDetail"> <transition on="updateData"> <render fragments="hoteldata"/> </transition> </view-state>
These fragments (in this case
hoteldata ) can be a comma-separated list of fragments specified in the markup using the
th: fragment :
<div id="data" th:fragment="hoteldata"> This is a content to be changed </div>
Always remember that these snippets must have an
id attribute so that Spring JavaScript libraries running in the browser can replace markup.
<Render> tags can also be specified using DOM selectors:
<view-state id = "detail" view = "bookingDetail">
/>
</ view-state>
... and this means that there is no need for
th: fragment :
<div id="data"> This is a content to be changed </div>
As for the code that launches the
updateData transition, it looks like this:
<script type="text/javascript" th:src="@{/resources/dojo/dojo.js}"></script> <script type="text/javascript" th:src="@{/resources/spring/Spring.js}"></script> <script type="text/javascript" th:src="@{/resources/spring/Spring-Dojo.js}"></script> ... <form id="triggerform" method="post" action=""> <input type="submit" id="doUpdate" name="_eventId_updateData" value="Update now!" /> </form> <script type="text/javascript"> Spring.addDecoration( new Spring.AjaxEventDecoration({formId:'triggerform',elementId:'doUpdate',event:'onclick'})); </script>