Thymeleaf template layout

Keywords: PHP Fragment Thymeleaf Attribute Javascript

Official documents: https://www.thymeleaf.org/doc/tutorials/3.0/usingthymeleaf.html

1. Define template fragments

Definition and reference fragments

 

In our pages, we often need to include parts in other templates, footers, titles, menus and so on...

To do this, Thymeleaf needs us to define these parts, "fragments" for inclusion, which can be done using the th:fragment attribute.

Suppose that we now define a template footer, so we create a file with the following code in / templates/footer.html:

<!DOCTYPE html>

<html xmlns:th="http://www.thymeleaf.org">

  <body>
  
    <font th:fragment="footer">
      &copy; 2011 The Good Thymes Virtual Grocery
    </font>
  
  </body>
  
</html>

Note: th:fragment="footer" defines the template as footer

The above code defines a fragment named footer that we can easily refer to on our home page with the th:replace attribute

<body><div th:insert="~{footer :: footer}"></div>
  
</body>

Note: th: insert = "~{footer:: footer}" refers to the footer template of the footer page, which can also be written as th: insert = "footer:: copy"

Page Running Effect:

 

perhaps

We can include fragments that do not use any th:fragment attribute

<!DOCTYPE html>

<html xmlns:th="http://www.thymeleaf.org">

  <body>
  
    <div id="footer">
      &copy; 2012 The Good Thymes Virtual Grocery
    </div>
  
  </body>
  
</html>

We can use the above fragment to simply reference it through its id attribute, similar to the CSS selector:

<body>

  <div th:insert="~{footer :: #copy-section}"></div>
  
</body>

Page Running Effect:

 

 

 

The difference between th:insert and th:replace

 

  • th:insert is the simplest: it simply inserts the specified fragment as the main body of its host tag.

  • th:replace actually replaces its host tag with the specified fragment.

<body>

  <div th:insert="footer :: copy"></div>

  <div th:replace="footer :: #copy"></div>
  
</body>

Page Running Effect:

 

 

2. Parametric fragments

To create a more functional mechanism for template fragments, you can specify a set of parameters using the defined fragment th:fragment

<div th:fragment="frag (onevar,twovar)">
    <p th:text="${onevar} + ' - ' + ${twovar}">...</p>
</div>

This requires th:insert or call fragment th:replace

<div th:replace="::frag (${value1},${value2})">...</div>
<div th:replace="::frag (onevar=${value1},twovar=${value2})">...</div>

Note that the order is variable in the last option

<div th:replace="::frag (twovar=${value2},onevar=${value1})">...</div>

Calling fragment local variables without fragment parameters

<div th:fragment="frag">
    ...
</div>

Assuming that there are no fragment parameters when local variables are invoked, only

<div th:replace="::frag (onevar=${value1},twovar=${value2})">

This would be equivalent to combining th:replace and th:with:

<div th:replace="::frag" th:with="onevar=${value1},twovar=${value2}">

3. Flexible layout

Defining templates

<head th:fragment="common_header(title,links)">

  <title th:replace="${title}">The awesome application</title>

  <!-- Common styles and scripts -->
  <link rel="stylesheet" type="text/css" media="all" th:href="@{/css/awesomeapp.css}">
  <link rel="shortcut icon" th:href="@{/images/favicon.ico}">
  <script type="text/javascript" th:src="@{/sh/scripts/codebase.js}"></script>

  <!--/* Per-page placeholder for additional links */-->
  <th:block th:replace="${links}" />

</head>

Reference template

<head th:replace="base :: common_header(~{::title},~{::link})">

  <title>Awesome - Main</title>

  <link rel="stylesheet" th:href="@{/css/bootstrap.min.css}">
  <link rel="stylesheet" th:href="@{/themes/smoothness/jquery-ui.css}">

</head>

Note: th: replace= "base:: common_header (~{:: title}, ~{:: link})" refers to template passing parameters.

It can also be passed on (th: replace= "base:: common_header (~{:: title}, ~{})

If the template parameter fragment has a default value, you want to use the default value, if you use no operation (th: replace= "base:: common_header (, ~{:: link})").

Page Running Effect:

 

 

4. Delete template fragments

Product List Template

<table>
  <tr>
    <th>NAME</th>
    <th>PRICE</th>
    <th>IN STOCK</th>
    <th>COMMENTS</th>
  </tr>
  <tr th:each="prod : ${prods}" th:class="${prodStat.odd}? 'odd'">
    <td th:text="${prod.name}">Onions</td>
    <td th:text="${prod.price}">2.41</td>
    <td th:text="${prod.inStock}? #{true} : #{false}">yes</td>
    <td>
      <span th:text="${#lists.size(prod.comments)}">2</span> comment/s
      <a href="comments.html" 
         th:href="@{/product/comments(prodId=${prod.id})}" 
         th:unless="${#lists.isEmpty(prod.comments)}">view</a>
    </td>
  </tr>
</table>

 

Why delete template fragments if the browser opens directly without Thymeleaf processing it, because although the browser can fully display, the table has only one row.

<tr class="odd">
      <td>Blue Lettuce</td>
      <td>9.55</td>
      <td>no</td>
      <td>
        <span>0</span> comment/s
      </td>
    </tr>
    <tr>
      <td>Mild Cinnamon</td>
      <td>1.99</td>
      <td>yes</td>
      <td>
        <span>3</span> comment/s
        <a href="comments.html">view</a>
      </td>
    </tr>

If static data is appended later, the data will be displayed regardless of whether Thymeleaf processes it or not.

Then the question arises, how can it display static data without Thymeleaf processing, and whether Thymeleaf processing does not display static data?

<tr class="odd" th:remove="all">
    <td>Blue Lettuce</td>
    <td>9.55</td>
    <td>no</td>
    <td>
      <span>0</span> comment/s
    </td>
  </tr>
  <tr th:remove="all">
    <td>Mild Cinnamon</td>
    <td>1.99</td>
    <td>yes</td>
    <td>
      <span>3</span> comment/s
      <a href="comments.html">view</a>
    </td>
  </tr>

What does this value in all attribute mean? Th: remote can be expressed in five different ways according to its value:

  • All: Delete the containing tag and all its subtags.
  • body: Do not delete the containing tag, but delete all its subtags.
  • Tag: Delete the containing tag, but do not delete its subitems.
  • all-but-first: Delete all subitems containing tags except the first.
  • none: Nothing. This value is useful for dynamic evaluation.

The th: remote attribute can be represented by any Thymeleaf standard because it returns one of the allowable string values as long as (all, tag, body, all-but-first or none).

This means that deletion may be conditional, for example:

<a href="/something" th:remove="${condition}? tag : none">Link text not to be removed</a>

Note also that th: remote considers the null synonym none, so the following works in the same way as the example above:

<a href="/something" th:remove="${condition}? tag">Link text not to be removed</a>

In this case, if ${condition} is false, null will return, so deletion will not be performed.

5. Layout Inheritance

To be able to lay out a single file, fragments can be used. An example of a simple layout with title and content using th:fragment sum

<!DOCTYPE html>
<html th:fragment="layout (title, content)" xmlns:th="http://www.thymeleaf.org">
<head>
    <title th:replace="${title}">Layout Title</title>
</head>
<body>
    <h1>Layout H1</h1>
    <div th:replace="${content}">
        <p>Layout content</p>
    </div>
    <footer>
        Layout footer
    </footer>
</body>
</html>

This example declares a fragment named layout with title and content as parameters. Both will be replaced on the page and inherited through the provided fragment expression in the following example.

<!DOCTYPE html>
<html th:replace="~{layoutFile :: layout(~{::title}, ~{::section})}">
<head>
    <title>Page Title</title>
</head>
<body>
<section>
    <p>Page content</p>
    <div>Included on page</div>
</section>
</body>
</html>

Result:

 

 

When passing parameters, different values can be passed by operation.

 

 

The data in this article are from 8 Template Layout on Thymeleaf.com

Posted by plsanders on Wed, 29 May 2019 04:07:13 -0700