Thymeleaf模板 - 有没有办法装饰模板而不是包含模板片段?

Rom*_*las 38 java spring-mvc thymeleaf

我是第一次与Thymeleaf合作,我需要澄清模板.如果我正确理解文档,我可以在我的页面中包含一个模板 - 或者只是一个片段.例如,我可以这样写:

<!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>
Run Code Online (Sandbox Code Playgroud)

但我想要的实际上是使用模板的相反方式:不是在页面中包含模板片段,我想我的模板中包含页面,类似于:

<!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>
Run Code Online (Sandbox Code Playgroud)

换句话说,有没有办法在Thymeleaf中拥有等效的Sitemesh装饰器标签

谢谢

Éri*_*oGR 67

使用Thymeleaf 2.1,您可以编写类似的内容:

创建模板(例如,模板/ layout.html),并在html标记中添加th:fragment ="page"信息,并使用th:include ="this :: content"信息定义内容区域:

<!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>
Run Code Online (Sandbox Code Playgroud)

现在创建将包含此模板的页面,在html标记中添加th:include ="templates/layout :: page",并将您的主要内容放入div中: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>
Run Code Online (Sandbox Code Playgroud)

在布局页面中,您可以使用(th:include ="this :: content")或禁止此选项(th:include =":: content").我认为这似乎是jsf facelets.

  • 这就是答案 (4认同)

Rom*_*las 20

好吧,正如Sotirios Delimanolis所说,Thymeleaf不支持使用模板的方式,或者我应该说" Hierarchical layouts ",正如Daniel Fernandez在这篇帖子中所解释的那样.

由于sitemesh和Thymeleaf兼容,似乎我必须使用这两种解决方案.太糟糕了.

编辑:正如DennisJaamann在评论中所建议的,我最终使用了Thymeleaf Layout Dialect,这是一种提供我正在寻找的功能的视图方言.

工作代码:

首先我添加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;
}
Run Code Online (Sandbox Code Playgroud)

然后,我创建模板(例如templates/layout.html),并添加layout:fragment我想要放置当前页面内容的信息:

<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>
Run Code Online (Sandbox Code Playgroud)

并且页面将引用具有以下属性的模板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>
Run Code Online (Sandbox Code Playgroud)