I am working with Thymeleaf for the first time, and I need a clarification about the templates. If I correctly understand the documentation, I can include a template - or just a fragment of it - in my page. So for example, I can write something like that:
<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml" xmlns:th="http://www.thymeleaf.org">
<head th:include="template/layout :: header">
</head>
<body>
Hello world
<div th:include="template/layout :: footer"></div>
</body>
</html>
But what I want is in fact the opposite way of using the template : instead of including template fragment in the page, I want to include the page inside my template, something like that:
<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml" xmlns:th="http://www.thymeleaf.org">
<head>
...
</head>
<body>
<div id="my-template-header">...</div>
<div id="the-content">
<!-- include here the content of the current page visited by the user -->
???
</div>
<div id="my-template-footer">...</div>
</body>
In others words, is there a way to have an equivalent of the Sitemesh decorators tags in Thymeleaf?
Thanks
Thymeleaf is way better in my opinion because it have good underlying priciples and exploits natural behaviour of browsers. Jsp makes html hard to read, it becomes weird mixture of html and java code which makes a lot of problems in comunication between designer - developer.
Thymeleaf template files are located in the custom src/main/resources/mytemplates directory. The default template directory is src/main/resources/templates . This is the Maven build file.
Variable expressions are OGNL expressions –or Spring EL if you're integrating Thymeleaf with Spring. *{} is used for selection expressions. Selection expressions are just like variable expressions, except they will be executed on a previously selected object. #{} is used for message (i18n) expressions.
with Thymeleaf 2.1, you can write something like that:
Create the template (for ex. templates/layout.html), and add the th:fragment="page" information in html tag and define the content area with th:include="this :: content" information:
<!DOCTYPE html> <html xmlns="http://www.w3.org/1999/xhtml" xmlns:th="http://www.thymeleaf.org" th:fragment="page"> <head> <meta http-equiv="Content-Type" content="text/html; charset=UTF-8" /> <title>Test</title> </head> <body> layout page <div th:include="this :: content"/> layout footer </body> </html>
Now create the page that will include this template adding th:include="templates/layout :: page" in html tag and put your main content inside a div with th:fragment="content"
<!DOCTYPE html> <html xmlns="http://www.w3.org/1999/xhtml" xmlns:th="http://www.thymeleaf.org" th:include="templates/layout :: page"> <head> <title></title> </head> <body> <div th:fragment="content"> my page content </div> </body> </html>
In layout page you can use this (th:include="this :: content") or suppress this option (th:include=":: content"). It seems like jsf facelets I think.
Ok, as stated by Sotirios Delimanolis, Thymeleaf does not support that way of using template, or should I say "Hierarchical layouts", as explained by Daniel Fernandez in this thread.
As sitemesh and Thymeleaf are compatible, it seems that I have to use both solutions. Too bad.
Edit: As suggested by DennisJaamann in a comment, I finally used Thymeleaf Layout Dialect, a view dialect that provides the feature I was looking for.
The working code:
First I add the LayoutDialect
class:
@Bean public ServletContextTemplateResolver templateResolver() { ServletContextTemplateResolver resolver = new ServletContextTemplateResolver(); resolver.setPrefix("/WEB-INF/views/"); resolver.setSuffix(".html"); //NB, selecting HTML5 as the template mode. resolver.setTemplateMode("HTML5"); resolver.setCacheable(false); return resolver; }
Then, I create the template (for ex. templates/layout.html
), and add the layout:fragment
information where I want to put the content of the current page:
<html xmlns="http://www.w3.org/1999/xhtml" xmlns:th="http://www.thymeleaf.org"> <head> ... </head> <body> <div id="my-template-header">...</div> <div id="the-content" layout:fragment="content"> <!-- include here the content of the current page visited by the user --> </div> <div id="my-template-footer">...</div> </body>
and the page will refers to the template with the attribute layout:decorator
:
<html xmlns="http://www.w3.org/1999/xhtml" xmlns:layout="http://www.ultraq.net.nz/thymeleaf/layout" layout:decorator="templates/layout"> <body> <div layout:fragment="content"> Hello world </div> </body> </html>
You need
<dependency>
<groupId>nz.net.ultraq.thymeleaf</groupId>
<artifactId>thymeleaf-layout-dialect</artifactId>
<version>1.2.2</version>
</dependency>
and add this to your SpringTemplateEngine:
@Bean
@Description("Thymeleaf template engine with Spring integration")
public SpringTemplateEngine templateEngine() {
SpringTemplateEngine templateEngine = new SpringTemplateEngine();
templateEngine.setTemplateResolver(templateResolver());
templateEngine.addDialect(new LayoutDialect());
return templateEngine;
}
If now create a folder named template in your views folder.
views/home.html
<html xmlns="http://www.w3.org/1999/xhtml"
xmlns:layout="http://www.ultraq.net.nz/thymeleaf/layout"
layout:decorator="template/layout">
<body>
<div layout:fragment="content">
Hello world
</div>
</body>
</html>
views/layout/layout.html
<!DOCTYPE html SYSTEM "http://www.thymeleaf.org/dtd/xhtml1-strict-thymeleaf-spring4-4.dtd">
<html xmlns="http://www.w3.org/1999/xhtml"
xmlns:th="http://www.thymeleaf.org"
xmlns:layout="http://www.ultraq.net.nz/thymeleaf/layout">
<head>
</head>
<body>
<div id="content" layout:fragment="content">
</div>
</body>
</html>
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With