Thymeleaf Tutorial

November 01, 2020 1 Comment Thymeleaf Tutorial Spring Boot

Thymeleaf is a Java-based template engine that allows to build dynamic pages using templates written in XML, XHTML or HTML. The engine provides a very pleasent way to inject logic into the templates. It uses XML tags and attributes just like HTML pages so even without starting web container we can check how the static page will look when it will be rendered. The engine allows a parallel work of the backend and frontend developers on the same view.

Thymeleaf attributes

Thymeleaf is an engine based on XML attributes. The engine evaluates values from attributes to build a DOM tree. Basing on attributes allows treating templates as simple static HTML documents that can be displayed in the browser without running any web application server. This is one of the reasons why Thymeleaf is so awesome.

Constructing URLs in Thymeleaf (th:href)
Using th:each in Thymeleaf (th:each)
Using conditions in Thymeleaf (th:if, th:switch)
Create data-* attribute with Thymeleaf (th:attr)
Working with Forms in Thymeleaf (th:action, th:field)
Using Enums in Thymeleaf (T)
Working with local variables in Thymeleaf (th:with)
Working with Thymeleaf dialects (fbe:header, fbe:welcome)

Thymeleaf utility methods

Thymeleaf comes with many useful utility classes that will help you in formatting and manipulating content on the templates. The engine provides methods for formatting string, parsing URI/URL, aggregating items in collections and processing common Java objects like Maps, Lists or Booleans.


Thymeleaf utility methods for URI/URL


Thymeleaf utility methods for Arrays


Thymeleaf utility methods for Booleans


Thymeleaf utility methods for Objects


Thymeleaf utility methods for Strings


Thymeleaf utility methods for Numbers


Thymeleaf utility methods for Calendar


Thymeleaf utility methods for Dates


Thymeleaf utility methods for Lists


Thymeleaf utility methods for messages

35+ UI Components with Thymeleaf

Thymeleaf can be used with many different web components written in all available JavaScript frameworks. This section presents commonly used HTML components working with and handled by the Thymeleaf engine.

Thymeleaf cheat sheet

Thymeleaf Expressions

Expression Examples Description
#{message.from.proprties.file} <p th:text="#{home.welcome}">Welcome to!</p>
Requires message bundle properties:
message expression
${variable} <span th:text="${customer.firstName}">Customer Name</span>
Other examples:
${x} will return a variable x stored into the Thymeleaf context or as a request attribute.
${param.x} will return a request parameter called x (which might be multivalued).
${session.x will return a session attribute called x.
${application.x} will return a servlet context attribute called x.
variable expression
*{field.attribute} <div th:object="${session.user}">
<p>Name: <span th:text="*{firstName}">Sebastian</span>.</p>
<p>Surname: <span th:text="*{lastName}">Pepper</span>.</p>
<p>Nationality: <span th:text="*{nationality}">Saturn</span>.</p>
expressions on selections
@{/home/path} Absolute URLs:

Relative URLs:
- Page-relative: @{view/user.html}
- Context-relative: @{/customer?id=3} (context name in server will be added automatically)
- Server-relative: @{~/invoice/payment} (allows calling URLs in another context (= application) in the same server.
- Protocol-relative URLs: @{//}

URLs with parameters:
@{/order/process(id=${id},type='FAST')} - /order/process?id=111&type=FAST
link URLs
~{commons :: fragment} /templates/footer.html
<!DOCTYPE html>
<html xmlns:th="">
<div th:fragment="copy">
2020 FrontBackend

Insert fragment in other template:
<div th:insert="footer :: copy"></div>
<div th:replace="footer :: copy"></div>
<div th:include="footer :: copy"></div>
fragment expressions
${#ctx} Methods from org.thymeleaf.context.IContext:

Methods from org.thymeleaf.context.IWebContext:
context object
${#vars} ${#vars.get('foo')}
context variables - org.thymeleaf.context.VariablesMap instance
${#locale} <span th:text="${}">US</span> the context locale - direct access to the java.util.Locale
${#request} ${#request.getAttribute('attribute1')}
direct access to javax.servlet.http.HttpServletRequest object
${#session} ${#session.getAttribute('sessionAttribute')}
the javax.servlet.http.HttpSession object of the current session
${#response} ${#response.status} the javax.servlet.http.HttpServletResponse object
${#dates} Date pattern syntax:
G - Era designator (before christ, after christ)
y - Year (e.g. 12 or 2012). Use either yy or yyyy.
M - Month in year. Number of M's determine length of format (e.g. MM, MMM or MMMMM)
d - Day in month. Number of d's determine length of format (e.g. d or dd)
h - Hour of day, 1-12 (AM / PM) (normally hh)
H - Hour of day, 0-23 (normally HH)
m - Minute in hour, 0-59 (normally mm)
s - Second in minute, 0-59 (normally ss)
S - Millisecond in second, 0-999 (normally SSS)
E - Day in week (e.g Monday, Tuesday etc.)
D - Day in year (1-366)
F - Day of week in month (e.g. 1st Thursday of December)
w - Week in year (1-53)
W - Week in month (0-5)
a - AM / PM marker
k - Hour in day (1-24, unlike HH's 0-23)
K - Hour in day, AM / PM (0-11)
z - Time Zone

${#dates.format(date, 'dd/MMM/yyyy HH:mm')}
utility methods for java.util.Date objects: formatting, component extraction
${#calendars} ${#calendars.format(cal, 'dd/MMM/yyyy HH:mm')}
utility methods for java.util.Calendar objects
${#numbers} 'POINT', 'COMMA', 'WHITESPACE', 'NONE' or 'DEFAULT' (by locale)
utility methods for formatting numeric objects
${#strings} ${#strings.isEmpty(name)}
${#strings.defaultString(text,default)} - default string when given is empty
${#strings.equals(first, second)}
${#strings.equalsIgnoreCase(first, second)}
utility methods for String objects
${#objects} ${#objects.nullSafe(obj,default)}
utility methods for objects in general
${#bools} ${#bools.isTrue(obj)}
utility methods for boolean evaluation
${#arrays} ${#arrays.length(array)}
${#arrays.contains(array, element)}
${#arrays.containsAll(array, elements)}
utility methods for arrays
${#lists} ${#lists.size(list)}
${#lists.contains(list, element)}
${#lists.containsAll(list, elements)}
${#lists.sort(list, comparator)}
utility methods for lists
${#sets} ${#sets.toSet(object)}
utility methods for sets
${#maps} ${#maps.containsKey(map, key)}
${#maps.containsAllKeys(map, keys)}
${#maps.containsValue(map, value)}
${#maps.containsAllValues(map, value)}
utility methods for maps
${#messages} ${#messages.msg('msgKey')}
${#messages.msg('msgKey', param1)}
${#messages.msg('msgKey', param1, param2)}
${#messages.msg('msgKey', param1, param2, param3)}
${#messages.msgWithParams('msgKey', new Object[] {param1, param2, param3, param4})}
utility methods for obtaining externalized messages inside variables expressions

Thymeleaf Attributes

Attribute Examples Description
th:text <h1 th:text="${post.title}">Title</h1>
Message expressions:

<p th:text="#{home.welcome}">Welcome to FrontBackend!</p> - simple

<p th:text="#{home.welcome(${})}">
Welcome to our grocery store, Martin Wojtus!
- for parametrized messages

String concatenation: <span th:text="'Welcome ' + ${}">
displaying HTML-encoded text that is evaluated from the expression
th:utext <div th:utext="${post.content}">Content</div>
displays text unescaped
th:attr Single:
<input type="submit" value="Subscribe!" th:attr="value=#{subscribe.submit}"/>

<img th:attr="src=@{/images/logo.png},title=#{logo},alt=#{logo}" />

Data attributes:
<div th:attr="data-id=${},data-title=${post.title},data-date=${#dates.format(, 'yyyy-MM-dd')}">
<th:block th:text="${post.title}">Post title</th:block>
sets the value of attribute
th:attrappend <input type="button" value="Do it!" class="btn" th:attrappend="class=${' ' + cssStyle}" />
appends the value to existing attribute
th:each <tr th:each="customer, custStat : ${customers}">
<td th:text="${custStat.index + 1}">1</td>
<td th:text="${customer.firstName}">John</td>
<td th:text="${customer.lastName}">Doe</td>
<td th:text="${customer.age}">18</td>
iteration attribute
th:if <div th:if="${user.isAdmin()}">...</div>
evaluates the conditions specified in the attribute and if they are true, the tag is displayed
th:unless <div th:unless="${user.isAdmin()}">.not admin..</div>
the opposite of th:if
th:switch, th:case <div th:switch="${user.role}">
<p th:case="'admin'">User is an administrator</p>
<p th:case="#{roles.manager}">User is a manager</p>
creating a switch statement
th:label, th:action, th:href, th:onclick etc. <form th:action="@{/sampleInputs}" th:object="${sampleInputs}" method="post">

<input type="text" th:field="*{dateField}" placeholder="yyyy-MM-dd" />

<input type="submit" value="Submit"/>
those attributes can be used as a shorthand of the th:attr syntax
th:with <div th:with="firstPer=${persons[0]}">
The name of the first person is <span th:text="${}">Julius Caesar</span>.
defining local variables
{{ message }}

{{ 'Comments are closed.' | trans }}