Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Thymeleaf templates - Is there a way to decorate a template instead of including a template fragment?

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

like image 841
Romain Linsolas Avatar asked Sep 19 '13 14:09

Romain Linsolas


People also ask

Which is better JSP or Thymeleaf?

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.

Where do I put Thymeleaf templates?

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.

What is #{} in Thymeleaf?

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.


3 Answers

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.

like image 170
ÉricoGR Avatar answered Oct 05 '22 22:10

ÉricoGR


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> 
like image 37
Romain Linsolas Avatar answered Oct 05 '22 22:10

Romain Linsolas


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>
like image 30
mrclrchtr Avatar answered Oct 05 '22 22:10

mrclrchtr