Использование Fragments в Thymeleaf

View more Tutorials:

1- Что такое Fragment?

Один  Fragment (Фрагмент) это часть в  Template. Thymeleaf позволяет вам импортировать fragment у данного  Template в другой  Template. Имеются много способов  определения одного  Fragment. Например:
  • Выбрать все теги (tag) с атрибутом (attribute) th:fragment="search-fragment".
  • Выбрать тег по ID.
  • Выбрать все таги по Css-class.
  • ....
Главное, когда вы хотите импортировать  Fragment у определенного  Template, вам нужно описать его расположение.
Синтаксис описания расположения  Fragment определенного  Template:

~{/path-to-template/template-name :: selector}
Если вы хотите описать расположение  Fragment определенного текущего  Template, то можете использовать более краткий синтаксис:
~{:: selector}

~{this :: selector}

~{templatename: fragmentname}  (th:fragment)

Выбрать  fragment по названию.

~{templatename: tagname}  (Tag Name)

Выбрать  fragment по названию тега.
Выбрать подтеги тега. Например, выбрать все теги  <script> расположенные в теге  <header>:

~{templatename: #id}   (ID)

Выбрать  fragment по значению атрибута (attribute) ID тега.

~{templatename: .classname},~{templatename: tagname.classname}   (Css Class)

Выбрать  fragment по  Css Class:

~{templatename}  (Everything)

Выбрать все в  Template:

Other...

Другие примеры:
~{fragments/my-template :: #tagId/text() }

~{fragments/my-template :: fragmentName/text() }

~{fragments/my-template :: tagName/text() }

2- th:insert, th:replace, th:include

Данное свойство позволяет импортировать  fragment из одного  Template в другой  Template действительно отлично, он помогает делать дизайн интерфейса вебсайта легче. Посмотрим пример ниже:
В данном примере, файл  my-template.html содержит многие  fragment, где другие  Template могут импортировать для использования.
/fragments/my-template.html
<!DOCTYPE HTML>
<html xmlns:th="http://www.thymeleaf.org">

<head>
    <meta charset="UTF-8" />
    
    
    <title>My Template</title>
    
    <link rel="stylesheet" type="text/css" th:href="@{/main.css}"/>
    <link rel="stylesheet" type="text/css" th:href="@{/secondary.css}"/>
    
    <script type="text/javascript" th:src="@{/main.js}"></script>
    <script type="text/javascript" th:src="@{/secondary.js}"></script>
    
</head>

<body>
    
    <!-- Script in body -->
    <script type="text/javascript" th:src="@{/script-in-body.js}"></script>

    <ul th:fragment="my-fragment1">
        <li><a th:href="@{/}">Home</a></li>
        <li><a th:href="@{/products}">Products</a></li>
        <li><a th:href="@{/about}">About</a></li>
    </ul>

    

    <ul th:fragment="my-fragment2">
        <li><a th:href="@{/admin/products}">Product Management</a></li>
        <li><a th:href="@{/admin/orders}">Order Management</a></li>
    </ul>
    
    
    <div id = "my-id1">
    
         Element DIV with id = 'my-id1'
       
    </div>
    
    
    <aside>
        <div>This is a sidebar</div>
    </aside>
    
    
    
    <p class="my-class">Element P with class (my-class)</p>
    
    <p>Element P without class</p>
    
    <p class="my-class">Element P with class (my-class)</p>
    

</body>
</html>
Файл  my-page.html является  Template, он импортирует некоторые fragment у  my-template.html:
my-page.html (Template)
<!DOCTYPE HTML>
<html xmlns:th="http://www.thymeleaf.org">
<head>
<meta charset="UTF-8" />
<title th:replace = "~{fragments/my-template :: title}">Title</title>


<th:block th:insert="~{fragments/my-template :: link}"></th:block>

<th:block th:insert="~{fragments/my-template :: head/script}"></th:block>

</head>
<body>
    
    
   <h1>My Page</h1>
  
   <p>Some Content of My Page</p>
    
    
   <div th:insert="~{fragments/my-template :: my-fragment1}"></div>
  
   <div th:insert="~{fragments/my-template :: my-fragment2}"></div>
  
  
   <div th:insert="~{fragments/my-template :: #my-id1}"></div>
  
  
   <div th:insert="~{fragments/my-template :: p.my-class }"></div>

</body>
</html>
Результат, который вы получаете:
(HTML Result)
<!DOCTYPE HTML>
<html>

<head>
    <meta charset="UTF-8" />
    <title>My Template</title>

    <link rel="stylesheet" type="text/css" href="/main.css" />
    <link rel="stylesheet" type="text/css" href="/secondary.css" />

    <script type="text/javascript" src="/main.js"></script>
    <script type="text/javascript" src="/secondary.js"></script>

</head>

<body>

    <h1>My Page</h1>

    <p>Some Content of My Page</p>

    <div>
        <ul>
            <li><a href="/">Home</a></li>
            <li><a href="/products">Products</a></li>
            <li><a href="/about">About</a></li>
        </ul>
    </div>

    <div>
        <ul>
            <li><a href="/admin/products">Product Management</a></li>
            <li><a href="/admin/orders">Order Management</a></li>
        </ul>
    </div>

    <div>
        <div id="my-id1">

            Element DIV with id = 'my-id1'

        </div>
    </div>

    <div>
        <p class="my-class">Element P with class (my-class)</p>
        <p class="my-class">Element P with class (my-class)</p>
    </div>

</body>

</html>

th:insert, th:replace, th:include

  • th:insert вставит Fragment становится подтегом целевого тега (Target tag).
  • th:replace заменит целевой тег с помощью Fragment.
  • th:include вставит дочерний Fragment становит дочерним целевым тегом.
Примечание: Атрибут(attribute) th:include используется в  Thymeleaf 2, и не используется больше в версии Thymeleaf 3.
/path/mytemplate.html (Fragments)
<footer th:fragment="copyright">
  &copy; o7planning.org
</footer>
Target Template:
(Target Template)
<body>

  ...
  <!-- th:insert -->
  <div th:insert="~{/path/mytemplate :: copyright}"></div>

  <!-- th:replace -->
  <div th:replace="~{/path/mytemplate :: copyright}"></div>

  <!-- th:include -->
  <div th:include ="~{/path/mytemplate :: copyright}"></div>

</body>
Результат:
(HTML Result)
<body>

  ...

  <!-- th:insert -->
  <div>
    <footer>
      &copy; o7planning.org
    </footer>
  </div>

  <!-- th:replace -->
  <footer>
    &copy; o7planning.org
  </footer>

  <!-- th:include -->
  <div>
    &copy; o7planning.org
  </div>
 
</body>

3- Fragment с параметрами

Один  fragment больше похож на функцию (function) если он имеет параметры, и удачно, что Thymeleaf это поддерживает.

Явный параметр:​​​​​​​

Если вы объявите  fragment и перечислите явным способом его параметры. Данные параметры будут обязательными параметрами. Как в примере ниже:
<div th:fragment="person (firstName, lastName)" class="box">
    <p>First Name: <span th:utext="${firstName}"></span></p>
    <p>Last Name: <span th:utext="${lastName}"></span></p>
    <p>Full Name: <span th:utext="${firstName} + ' '+ ${lastName}"></span></p>
</div>
Передача параметров, когда вы вызываете  fragment:
<div th:replace="~{fragments/my-template2 :: person('Donald', 'Trump') }"></div>
    
<div th:replace="~{fragments/my-template2 :: person( firstName='Donald', lastName= 'Trump') }"></div>

<div th:replace="~{fragments/my-template2 :: person( ${u.firstName}, ${u.lastName}) }"></div>

<div th:replace="~{fragments/my-template2 :: person( firstName=${u.firstName}, lastName= ${u.lastName}) }"></div>

Неявный параметр

Вы можете создать fragment с неявными параметрами, они являются необязательными параметрами, как в следующем примере:
<!-- Fragment with implicit parameters. -->
<div th:fragment="greeting" class="box">
    <p>Hello
       <span th:utext="${title}"></span>
       <span th:utext="${name} ?: 'There'"></span>
    </p>
</div>
Вызвать  fragment с неявными параметрами.
<div th:replace="~{fragments/my-template2 :: greeting(title='Mr.', name = 'Tom') }"></div>    
    
<div th:replace="~{fragments/my-template2 :: greeting }"></div>   

4- th:assert

Атрибут (attribute) th:assert помогает вам оценить выражение или много выражений (Выражения отделены запятой). Если выражения оценены как true (верно) нет никаких проблем, если есть 1 выражение оцененное как false (ошибка) выбрасывается исключение.
<div th:fragment="employee (firstName, lastName)" class="box"
     th:assert= "${!#strings.isEmpty(firstName)}, ${!#strings.isEmpty(lastName)}">
     
    <p>First Name: <span th:utext="${firstName}"></span></p>
    <p>Last Name: <span th:utext="${lastName}"></span></p>
    <p>Full Name: <span th:utext="${firstName} + ' '+ ${lastName}"></span></p>
    
</div>

View more Tutorials: