Использование Fragments в Thymeleaf
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">
© 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>
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>
Pуководства Thymeleaf
- Оператор Elvis в Thymeleaf
- Цикл в Thymeleaf
- Условные операторы if, unless, switch в Thymeleaf
- Предопределенные объекты в Thymeleaf
- Использование Thymeleaf th:class, th:classappend, th:style, th:styleappend
- Введение в Thymeleaf
- Переменные (Variables) в Thymeleaf
- Использование Fragments в Thymeleaf
- Используйте Layout в Thymeleaf
- Использование Thymeleaf th:object и синтаксиса asterisk *{ }
- Пример Thymeleaf Form Select option
Show More