Thymeleaf templates - Is there a way to decorate a template instead of including a template fragment?
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:
@Beanpublic 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>