Использование Fragments в Thymeleaf
View more Tutorials:
Один 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() }
Данное свойство позволяет импортировать 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"> © 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> © o7planning.org </footer> </div> <!-- th:replace --> <footer> © o7planning.org </footer> <!-- th:include --> <div> © o7planning.org </div> </body>
Один 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>
Атрибут (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>