Thymeleaf module
This is a Play framework module to use Thymeleaf 2.0 as a template engine.
Thymeleaf mainly uses the xml attributes, keeping the XML/XHTML/HTML5 templates well-formed. As the official site says, those can be correctly displayed by browsers and therefore work also as static prototypes.
This is NOT a whole replacement of the groovy template. It is rather an add-on, rendering thymeleaf template only if the alternative template exists.
Sample application
Check out the “Yet Another Blog Engine” in the samples-and-tests directory. It is copied from the framework original sample app, except groovy template files in “app/views/Application” are all replaced by the thymeleaf template files in “app/thviews”, but you can get the same output.
Be sure to do “play deps” before you run the app.
Getting started
Add the following line to your dependencies.yml:
require:
- play
- play -> thymeleaf 0.0.1
and call “play deps”. Remove 404.html and 500.html in “app/views”. (the html errors are routed to thymeleaf template)
Configuration
These are the options with default values.
thymeleaf.prefix=${application.path}/app/thviews
The place where you put thymeleaf template files
thymeleaf.suffix=
thymeleaf.templatemode=XHTML
template mode of the engine
thymeleaf.cache.ttl=
template chache ttl in milliseconds for production mode. They are not cached in DEV mode.
thymeleaf.enhancer.enabled=true
whether to enhance the application classes in order to remove “synthetic” flags for OGNL
Usage
Put thymeleaf well-formed template files like below in “app/thviews” (by default).
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en" xmlns:th="http://www.thymeleaf.org">
<body>
<span th:text="${someObj.name}">The name comes here.</span>
</body>
</html>
Please refer to the official documentation for the attribute and expressions usage.
Play specific processors
Action Processor
There are some custom processors included in the module for action string conversion.
The value of the attribute names below can be parsed as an action string.
- action
- href
- name
- src
- type
- value
For example, define pl namespace and put some action string similar to groovy one, except for “${}”.<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en" xmlns:th="http://www.thymeleaf.org" xmlns:pl="http://www.playframework.org" >
<body>
<a href="anotherPage.html" pl:href="Application.anotherAction(someObj.id)">Link</a>
</body>
</html>
You can get the parsed link as expected since the string inside () is parsed as an OGNL expression within the same context of the page.
Form Processor
It acts like Fasttag #{form /}. Authentication token hidden element will be inserted if the method is post.
The default method of the form is ‘GET’ contrary to Groovy template. You can override it with a normal html attribute like below:
<form pl:form="Put.yourAction()" method="post" >
...</form>
Error Processor
“error” Attribute Processor acts like #{error /} tag in Groovy template. In the sample code below, the span tag appears only if there is an error.
<input type="text" name="user.name" th:value="${user?user.name:null}" /><span class="error" pl:error="user.name">validation error comes here.</span>
Extra implicit objects
- play.templates.JavaExtensions instance is availabe as ‘ext’: ${ext.nl2br(‘line\nNewline’)}
Message Resolution
By default, thymeleaf’s StandardMessageReolver is used. Add PlayMessageResolver to TemplateEngine so that the messages are resolved by play.i18n.Messages.
Play.plugin(ThymeleafPlugin.class)
.getTemplateEngine()
.addMessageResolver(new PlayMessageResolver());
Notice
OGNL and class enhancement
Thymeleaf makes use of OGNL as a standard template expression language, and it does not handle any method that has ‘synthetic’ flag, while Play! PropertiesEnhancer marks the generated implicit getter/setter methods ‘synthetic’ for a class that has public properties. Suppose you have model classes User and Address:
public class User {
public Address address;
}public class Address {
public String street;
}
The Play enhancer generates method User#getAddress() and Address#getStreet(), then a call from OGNL like:
<span th:text="${user.address.street}"></span>
would result in NPE because it cannot invoke the method. So the module re-enhances application classes and removes synthetic flags in order to treat the enhanced objects like normal Java beans. You can turn this off by a configuration parameter in case other precedent modules use the flags. “${addr=user.address, addr.street}” can produce the same result.