web-dev-qa-db-fra.com

Modèles Thymeleaf - Existe-t-il un moyen de décorer un modèle au lieu d'inclure un fragment de modèle?

Je travaille avec Thymeleaf pour la première fois et j'ai besoin d'une clarification sur les modèles. Si je comprends bien la documentation, je peux - inclure un modèle - ou juste un fragment de celui-ci - dans ma page. Ainsi, par exemple, je peux écrire quelque chose comme ça:

<!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>

Mais ce que je veux, c'est en fait la façon opposée d'utiliser le modèle: au lieu d'inclure un fragment de modèle dans la page, je veux inclure la page à l'intérieur mon modèle, quelque chose comme ça:

<!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>

En d'autres termes, existe-t-il un moyen d'avoir un équivalent des balises de décorateurs Sitemesh dans Thymeleaf?

Merci

38
Romain Linsolas

Ok, comme indiqué par Sotirios Delimanolis, Thymeleaf ne prend pas en charge cette façon d'utiliser le modèle, ou devrais-je dire " Dispositions hiérarchiques ", comme expliqué par Daniel Fernandez dans ce fil .

Comme sitemesh et Thymeleaf sont compatibles, il semble que je doive utiliser les deux solutions. Dommage.

Edit: Comme suggéré par DennisJaamann dans un commentaire, j'ai finalement utilisé Thymeleaf Layout Dialect , un dialecte de vue qui fournit la fonctionnalité que je cherchais.

Le code de travail:

J'ajoute d'abord la classe LayoutDialect:

@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;
}

Ensuite, je crée le modèle (par ex. templates/layout.html) et ajoutez le layout:fragment informations où je veux mettre le contenu de la page actuelle:

<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>

et la page fera référence au modèle avec l'attribut 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>
20
Romain Linsolas

avec Thymeleaf 2.1, vous pouvez écrire quelque chose comme ça:

Créez le modèle (par exemple templates/layout.html), et ajoutez les informations th: fragment = "page" dans la balise html et définissez la zone de contenu avec th: include = " this :: content " informations:

<!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>

Créez maintenant la page qui inclura ce modèle en ajoutant th: include = "templates/layout :: page" dans la balise html et mettez votre contenu principal dans une div avec th: fragment = " contenu "

<!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>

Dans la page de mise en page, vous pouvez utiliser this (th: include = "this :: content") ou supprimer cette option (th : include = ":: content"). On dirait des facettes jsf je pense.

67
ÉricoGR

Vous avez besoin

<dependency>
    <groupId>nz.net.ultraq.thymeleaf</groupId>
    <artifactId>thymeleaf-layout-dialect</artifactId>
    <version>1.2.2</version>
</dependency>

et ajoutez ceci à votre 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;
}

Si maintenant, créez un dossier nommé modèle dans votre dossier de vues.

vues/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>
1
mrclrchtr

Pour autant que je sache, vous ne pouvez pas. Une solution possible serait de créer un ViewResolver qui transmet toujours à votre fichier decorator, mais en même temps, mettez des attributs Model qui auraient le chemin réel vers le fragment que vous veulent inclure.

0