Mostly yes. While (as of 2016) there is no browser that fully implements the whole HTML5 feature set, most of the common ones do implement a large part of it. So as long as your users are not stuck with very old versions of (now-defunct) Internet Explorer, you should be fine in most scenarios.
Also, note that browser support actually evolves with time not only because of the quick pace at which browsers release new versions, but also because the specification itself is still work in progress.
-
For a list of HTML5 features and the corresponding browser support, check the Can I use… website. Notably, the HTML5 category list for all of the features: http://caniuse.com/#cats=HTML5
+
For a list of HTML5 features and the corresponding browser support, check the Can I use… website. Notably, the HTML5 category list for all of the features: http://caniuse.com/#cats=HTML5
In the above example, we are building a page that consists of page header and page footer. In Thymeleaf all fragments can be defined in a single file (e.g. fragments.html) or in a separate files, like in this particular case.
+
In the above example, we are building a page that consists of page header and page footer. In Thymeleaf all fragments can be defined in a single file (e.g. fragments.html) or in a separate files, like in this particular case.
The first part of the statement, fragments/header, is a template name that we are referencing. This can be a file (like in this example) or it can reference to the same file either by using the this keyword (e.g. this :: header) or without any keyword (e.g. :: header). The expression after double colon is a fragment selector (either fragment name or Markup Selector). As you can also see, the header fragment contains a markup that is used for static prototyping only.
+
The first part of the statement, fragments/header, is a template name that we are referencing. This can be a file (like in this example) or it can reference to the same file either by using the this keyword (e.g. this :: header) or without any keyword (e.g. :: header). The expression after double colon is a fragment selector (either fragment name or Markup Selector). As you can also see, the header fragment contains a markup that is used for static prototyping only.
Header and footer are defined in the following files:
Template fragments/header.html
<!DOCTYPE html>
@@ -226,7 +226,7 @@
Basic inclusion with th:insert and th:replace
Including with Markup Selectors
In Thymeleaf, fragments don’t need to be explicitly specified using th:fragment at the page they are extracted from. Thymeleaf can select an arbitrary section of a page as a fragment (even a page living on an external server) by means of its Markup Selector syntax, similar to XPath expressions, CSS or jQuery selectors.
The above code will include a section with class="description" from thymeleaf.org.
+
The above code will include a section with class="description" from thymeleaf.org.
In order to make it happen, the template engine must be configured with UrlTemplateResolver:
@Bean
public SpringTemplateEngine templateEngine() {
@@ -463,7 +463,7 @@
Creating a layout
Layout page
-
The above file is our decorator for content pages we will be creating in the application. The most important thing about the above example is layout:fragment="content". This is the heart of the decorator page (layout). You can also notice, that header and footer are included using Standard Thymeleaf Layout System.
+
The above file is our decorator for content pages we will be creating in the application. The most important thing about the above example is layout:fragment="content". This is the heart of the decorator page (layout). You can also notice, that header and footer are included using Standard Thymeleaf Layout System.
The content page looks as follows (WEB-INF/views/task/list.html):
Content of this task/list view will be decorated by the elements of task/layout view. Please note layout:decorate="~{task/layout}" attribute in <html> element. This attribute signals to the Layout Dialect which layout should be used to decorate given view. And please note it is using Thymeleaf Fragment Expression syntax.
+
Content of this task/list view will be decorated by the elements of task/layout view. Please note layout:decorate="~{task/layout}" attribute in <html> element. This attribute signals to the Layout Dialect which layout should be used to decorate given view. And please note it is using Thymeleaf Fragment Expression syntax.
And what about Natural Templates using the Layout Dialect? Again, possible! You simply need to add some prototyping-only markup around the fragments being included in your templates and that’s it!
@@ -584,7 +584,7 @@
Thymeleaf Custom Layout
Controllers return view names, that translate to single Thymeleaf view file (1)
Before rendering the view, the original viewName attribute in ModelAndView object is replaced with with the name of the layout view and the original viewName becomes an attribute in ModelAndView.
-
The layout view (2) contains several include elements: <div th:replace="${view} :: content">Page Content</div>
+
The layout view (2) contains several include elements: <div th:replace="${view} :: content">Page Content</div>
The actual view file contains fragments, pulled by the template which embeds the actual view
And it works just fine… but we want to add some nice additional features. For example:
-
Allow Spring EL expressions as attribute values, like in most tags in the Spring Thymeleaf Dialect. For example: hello:sayto="${user.name}"
+
Allow Spring EL expressions as attribute values, like in most tags in the Spring Thymeleaf Dialect. For example: hello:sayto="${user.name}"
Internationalize output: say Hello for English, Hola for Spanish, Olá for Portuguese, etc.
And we will need all that because we want to be able to create a new attribute, called “saytoplanet” and salute all the planets in the solar system, with a template like this:
All the code in this article comes from a working example application. You can view or download the source from its GitHub repo. Downloading this application, executing it and exploring its source code is highly recommended (note that you will have to configure your SMTP user name and password (and your SMTP server if you are not using GMail) at src/main/resources/configuration.properties).
+
All the code in this article comes from a working example application. You can view or download the source from its GitHub repo. Downloading this application, executing it and exploring its source code is highly recommended (note that you will have to configure your SMTP user name and password (and your SMTP server if you are not using GMail) at src/main/resources/configuration.properties).
Spring MVC and Thymeleaf: how to access data from templates
In a typical Spring MVC application, @Controller classes are responsible for preparing a model map with data and selecting a view to be rendered. This model map allows for the complete abstraction of the view technology and, in the case of Thymeleaf, it is transformed into a Thymeleaf context object (part of the Thymeleaf template execution context) that makes all the defined variables available to expressions executed in templates.
-
-
Spring model attributes
-
Spring MVC calls the pieces of data that can be accessed during the execution of views model attributes. The equivalent term in Thymeleaf language is context variables.
-
There are several ways of adding model attributes to a view in Spring MVC. Below you will find some common cases:
-
Add attribute to Model via its addAttribute method:
As you may have noticed, in all the above cases the messages attribute is added to the model and it will be available in Thymeleaf views.
-
In Thymeleaf, these model attributes (or context variables in Thymeleaf jargon) can be accessed with the following syntax: ${attributeName}, where attributeName in our case is messages. This is a Spring EL expression. In short, Spring EL (Spring Expression Language) is a language that supports querying and manipulating an object graph at runtime.
-
You can access model attributes in views with Thymeleaf as follows:
Note: If you access multivalued parameter with ${param.q} you will get a serialized array as a value.
-
Another way to access request parameters is by using the special #request object that gives you direct access to the javax.servlet.http.HttpServletRequest object:
Or by using #session, that gives you direct access to the javax.servlet.http.HttpSession object: ${#session.getAttribute('mySessionAttribute')}
-
-
-
ServletContext attributes
-
The ServletContext attributes are shared between requests and sessions. In order to access ServletContext attributes in Thymeleaf you can use the #servletContext. prefix:
In the above example, @urlService refers to a Spring Bean registered at your context, e.g.
-
@Configuration
- public class MyConfiguration {
- @Bean(name = "urlService")
- public UrlService urlService() {
- return () -> "domain.com/myapp";
- }
+
+
Spring model attributes
+
Spring MVC calls the pieces of data that can be accessed during the execution of views model attributes. The equivalent term in Thymeleaf language is context variables.
+
There are several ways of adding model attributes to a view in Spring MVC. Below you will find some common cases:
+
Add attribute to Model via its addAttribute method:
As you may have noticed, in all the above cases the messages attribute is added to the model and it will be available in Thymeleaf views.
+
In Thymeleaf, these model attributes (or context variables in Thymeleaf jargon) can be accessed with the following syntax: ${attributeName}, where attributeName in our case is messages. This is a Spring EL expression. In short, Spring EL (Spring Expression Language) is a language that supports querying and manipulating an object graph at runtime.
+
You can access model attributes in views with Thymeleaf as follows:
Note: If you access multivalued parameter with ${param.q} you will get a serialized array as a value.
+
Another way to access request parameters is by using the special #request object that gives you direct access to the javax.servlet.http.HttpServletRequest object:
Or by using #session, that gives you direct access to the javax.servlet.http.HttpSession object: ${#session.getAttribute('mySessionAttribute')}
+
+
+
ServletContext attributes
+
The ServletContext attributes are shared between requests and sessions. In order to access ServletContext attributes in Thymeleaf you can use the #servletContext. prefix:
Have you switched to Thymeleaf but your login and error pages are still using JSP? In this article we will see how to configure your Spring application to use Thymeleaf for login and error pages.
-
All the code seen here comes from a working application. You can view or download the source code from its GitHub repo.
+
All the code seen here comes from a working application. You can view or download the source code from its GitHub repo.
Note that the Thymeleaf integration packages for Spring Security support both Spring MVC and Spring WebFlux applications since Spring Security 5, but this article will focus on a Spring MVC configuration.
Getting started with the Standard dialects in 5 minutes
Standard dialects?
Thymeleaf is very, very extensible, and it allows you to define your own sets of template attributes (or even tags) with the names you want, evaluating the expressions you want in the syntax you want and applying the logic you want. It’s more like a template engine framework.
-
Out of the box, nevertheless, it comes with something called the standard dialects (named Standard and SpringStandard) that define a set of features which should be more than enough for most scenarios. You can identify when these standard dialects are being used in a template because it will contain attributes starting with the th prefix, like <span th:text="...">.
+
Out of the box, nevertheless, it comes with something called the standard dialects (named Standard and SpringStandard) that define a set of features which should be more than enough for most scenarios. You can identify when these standard dialects are being used in a template because it will contain attributes starting with the th prefix, like <span th:text="...">.
Note that the Standard and the SpringStandard dialects are almost identical, except that SpringStandard includes specific features for integrating into Spring MVC applications (like, for example, using Spring Expression Language for expression evaluation instead of OGNL).
Also note we usually refer to features in the Standard dialects when we talk about Thymeleaf without being more specific.
In this article we will compare the same page (a subscription form) created twice for the same Spring MVC application: once using Thymeleaf and another time using JSP, JSTL and the Spring tag libraries.
-
All the code seen here comes from a working application. You can view or download the source code from its GitHub repo.
+
All the code seen here comes from a working application. You can view or download the source code from its GitHub repo.
Common requirements
Our customers need a form for subscribing new members to a message list, with two fields:
@@ -231,7 +231,7 @@
Changing the page style using Thymeleaf
Thymeleaf page - valid as a prototype
-
Step 2: Open the .css file with our favourite text editor. The template file statically links to the CSS in its <link rel="stylesheet" ...> tag (with an href that Thymeleaf substitutes when executing the template by the one generated by th:href). So any changes we make to that CSS will be applied to the static page our browser is displaying.
+
Step 2: Open the .css file with our favourite text editor. The template file statically links to the CSS in its <link rel="stylesheet" ...> tag (with an href that Thymeleaf substitutes when executing the template by the one generated by th:href). So any changes we make to that CSS will be applied to the static page our browser is displaying.
Step 3: Make the colour changes. As was the case with JSP, we will probably have to try several colour combinations, which will be refreshed in our browser just by pressing F5.
Done!
@@ -265,7 +265,7 @@
And what about trying to use the JSP as a static prototype?
Got HTML5?
But hey – we said at the beginning that our page was going to be HTML5, so… why don’t we use some of the cool new HTML5 form-related features?
-
For example, there is now an <input type="email" ...>, which will make our browser check that the text input by users has the shape of an email address. And also, there is a new property for all inputs called placeholder which shows a text in the field that automatically dissapears when the input gains focus (usually by the user clicking on it).
+
For example, there is now an <input type="email" ...>, which will make our browser check that the text input by users has the shape of an email address. And also, there is a new property for all inputs called placeholder which shows a text in the field that automatically dissapears when the input gains focus (usually by the user clicking on it).
Sounds good, doesn’t it? Unfortunately not all browsers support this yet (as of 2011, Opera 11 and Firefox 4 do), but we are safe using these features anyway because all browsers will treat an input of a type they do not understand (email) as a text input, and will silently ignore the placeholder attribute in the same way they ignore Thymeleaf’s th:* ones.
Let’s have a quick look at each of the important new concepts and features this new version brings:
Template changes
-
The only change we recommend doing to your templates is removing any th:inline="text" attributes you might have, because they are not needed anymore in order to have output inlined expressions in HTML or XML templates. And it’s just a recommendation — templates will work anyway. But you will benefit from some extra processing performance if you remove those.
+
The only change we recommend doing to your templates is removing any th:inline="text" attributes you might have, because they are not needed anymore in order to have output inlined expressions in HTML or XML templates. And it’s just a recommendation — templates will work anyway. But you will benefit from some extra processing performance if you remove those.
See more information about this below in the Improved inlining mechanism section.
@@ -153,7 +153,7 @@
Template modes
There are two markup template modes (HTML and XML), three textual template modes (TEXT, JAVASCRIPT and CSS) and a no-op template mode (RAW).
The HTML template mode will admit any kind of HTML markup input, including HTML5, HTML 4 and XHTML. No markup validation of well-formedness check will be performed, and template markup code structure will be respected to the biggest possible extent in output.
The new textual template modes bring to Thymeleaf the ability to output CSS, Javascript and plain text. This is handy if you want to use the values of server-side variables in your CSS and Javascript files, or to generate plain text content as, for example, in e-mail composing.
@@ -168,7 +168,7 @@
Improved inlining mechanism
Sometimes it is handy to be able to output data without using extra tags or attributes, as in:
<p>This product is called [[${product.name}]] and it's great!</p>
This capability, called inlining, has been greatly improved and is now much better supported in Thymeleaf 3. See Inlined output expressions for details.
-
The existing inlining mechanism also matches the new template modes and, indeed, make innecesary the th:inline="text" attribute because inlining now exists in HTML mode itself. Take a look at the discussion on Refactoring of the inlining mechanism
+
The existing inlining mechanism also matches the new template modes and, indeed, make innecesary the th:inline="text" attribute because inlining now exists in HTML mode itself. Take a look at the discussion on Refactoring of the inlining mechanism
diff --git a/doc/tutorials/3.1/extendingthymeleaf.epub b/doc/tutorials/3.1/extendingthymeleaf.epub
index c912c76a7..58e205ba8 100644
Binary files a/doc/tutorials/3.1/extendingthymeleaf.epub and b/doc/tutorials/3.1/extendingthymeleaf.epub differ
diff --git a/doc/tutorials/3.1/extendingthymeleaf.html b/doc/tutorials/3.1/extendingthymeleaf.html
index 663f47824..ab52d5b5e 100644
--- a/doc/tutorials/3.1/extendingthymeleaf.html
+++ b/doc/tutorials/3.1/extendingthymeleaf.html
@@ -806,7 +806,7 @@
Accessing i18n messages
Message resolution is an extension point in Thymeleaf (IMessageResolver interface), and therefore how these parameters are treated depends on the specific implementation being used. The default implementation in non-Spring-enabled applications (StandardMessageResolver) will do the following:
First look for .properties files with the same name as the template file + the locale. So if the template is /views/main.html and locale is gl_ES, it will look for /views/main_gl_ES.properties, then /views/main_gl.properties and last /views/main.properties.
-
If not found, then use the origin class (which could have been specified null) and look for .properties files in classpath with the name of the class specified there (the processor’s own class): classpath:thymeleafexamples/extrathyme/dialects/score/RemarkForPositionAttributeTagProcessor_gl_ES.properties, etc. This allows the componentization or processors and dialects with their whole set of i18n resource bundles in plain old .jar files.
+
If not found, then use the origin class (which could have been specified null) and look for .properties files in classpath with the name of the class specified there (the processor’s own class): classpath:org/thymeleaf/examples/spring6/extrathyme/dialects/score/RemarkForPositionAttributeTagProcessor_gl_ES.properties, etc. This allows the componentization or processors and dialects with their whole set of i18n resource bundles in plain old .jar files.
If none of these are found, have a look at the absent message representation flag. If false, simply return null. If true, create some kind of text that will allow the developer or user to quickly identify the fact that an i18n resource is missing: ??remarks.rel_gl_ES??.
(Note that, in Spring-enabled applications, this message resolution mechanism will be replaced by default with Spring’s own, based on the MessageSource beans declared at the Spring Application Context.)
diff --git a/doc/tutorials/3.1/extendingthymeleaf.mobi b/doc/tutorials/3.1/extendingthymeleaf.mobi
index 68f3ecd25..5ac7d1eb2 100644
Binary files a/doc/tutorials/3.1/extendingthymeleaf.mobi and b/doc/tutorials/3.1/extendingthymeleaf.mobi differ
diff --git a/doc/tutorials/3.1/extendingthymeleaf.pdf b/doc/tutorials/3.1/extendingthymeleaf.pdf
index 518ec7408..225c9f3df 100644
Binary files a/doc/tutorials/3.1/extendingthymeleaf.pdf and b/doc/tutorials/3.1/extendingthymeleaf.pdf differ
diff --git a/doc/tutorials/3.1/thymeleafspring.epub b/doc/tutorials/3.1/thymeleafspring.epub
index b6b07c0b9..957fa401f 100644
Binary files a/doc/tutorials/3.1/thymeleafspring.epub and b/doc/tutorials/3.1/thymeleafspring.epub differ
diff --git a/doc/tutorials/3.1/thymeleafspring.mobi b/doc/tutorials/3.1/thymeleafspring.mobi
index 71feb226c..320e06804 100644
Binary files a/doc/tutorials/3.1/thymeleafspring.mobi and b/doc/tutorials/3.1/thymeleafspring.mobi differ
diff --git a/doc/tutorials/3.1/thymeleafspring.pdf b/doc/tutorials/3.1/thymeleafspring.pdf
index a9a1ff0f1..06769ad95 100644
Binary files a/doc/tutorials/3.1/thymeleafspring.pdf and b/doc/tutorials/3.1/thymeleafspring.pdf differ
diff --git a/doc/tutorials/3.1/usingthymeleaf.epub b/doc/tutorials/3.1/usingthymeleaf.epub
index 62871b284..d6a450885 100644
Binary files a/doc/tutorials/3.1/usingthymeleaf.epub and b/doc/tutorials/3.1/usingthymeleaf.epub differ
diff --git a/doc/tutorials/3.1/usingthymeleaf.mobi b/doc/tutorials/3.1/usingthymeleaf.mobi
index 99d3b7aff..f3576662e 100644
Binary files a/doc/tutorials/3.1/usingthymeleaf.mobi and b/doc/tutorials/3.1/usingthymeleaf.mobi differ
diff --git a/doc/tutorials/3.1/usingthymeleaf.pdf b/doc/tutorials/3.1/usingthymeleaf.pdf
index 1d2a94430..40160dee8 100644
Binary files a/doc/tutorials/3.1/usingthymeleaf.pdf and b/doc/tutorials/3.1/usingthymeleaf.pdf differ