Just like methods in Java provide us with the ability to reuse useful code, Thymeleaf allows us to do something similar with HTML.
Fragments are blocks of HTML elements that we want to use across multiple
templates. The fragments are stored in a separate file, and they can be
accessed by using the keywords fragment
and replace
.
A summary of these two keywords is given below, followed by another video walkthrough to give you some more live-coding practice.
Anytime you find yourself typing identical code into different templates, you should consider ways to streamline your work.
Never fear, coder. Fragments are the tool you need. The general syntax is:
th:fragment = "fragmentName"
th:replace = "fileName :: fragmentName"
th:fragment
¶Let’s assume that you want to add the same styled header and a set of links to multiple pages within your web project.
Examples
The common header styled with CSS:
1 | <h1 class="fancyTitle" th:text="${title}"></h1>
|
The link list, which appears below a dividing line:
1 2 3 4 | <hr>
<a href = "https://www.launchcode.org">LaunchCode</a> <br/>
<a href = "https://www.lego.com">Play Well</a> <br/>
<a href = "https://www.webelements.com">Other Building Blocks</a>
|
Instead of pasting this code into every template, we will store the HTML in a separate file.
Create a new html file inside the templates
folder and give it a clear
name (e.g. fragments.html
is a common practice).
Inside this file, use the th:fragment
attribute on each block of code
that you want to reuse. Note that you must provide a different name for each
sample.
Examples
For the h1
element:
1 | <h1 th:fragment = "styledHeader" class="fancyTitle" th:text="${title}"></h1>
|
For multiple elements, we need to wrap them in another tag:
1 2 3 4 5 6 | <div th:fragment = "linkList">
<hr>
<a href = "https://www.launchcode.org">LaunchCode</a> <br/>
<a href = "https://www.lego.com">Play Well</a> <br/>
<a href = "https://www.webelements.com">Other Building Blocks</a>
</div>
|
We can now pull either of the fragments—styledHeader
or
linkList
–into any template in our project.
Tip
What if we do not want to keep the link list inside its own div
element?
One option is to use th:block
:
1 2 3 4 5 6 | <th:block th:fragment = "linkList">
<hr>
<a href = "https://www.launchcode.org">LaunchCode</a> <br/>
<a href = "https://www.lego.com">Play Well</a> <br/>
<a href = "https://www.webelements.com">Other Building Blocks</a>
</th:block>
|
Another option is to use the attribute th:remove
, which allows us to
selectively discard the wrapper tag, but not any of its children.
1 | <div th:fragment = "linkList" th:remove = "tag">
|
For a more detailed discussion of the different th:remove
options, consult
the Thymeleaf documentation.
th:replace
¶This attribute does just what the name implies—it replaces the tag that
contains it with the selected fragment. Thus, if the fragment is a <p>
element, and the template contains <div th:replace = "...">
, then the
div
in the template will be replaced with a p
. Similarly, if the
fragment contains multiple elements, the single template tag will be replaced
with the entire code block.
Take home lesson: The template tag that contains th:replace
does NOT have
to match the HTML tags in the fragment.
Now let’s see how to pull fragments into a template:
Examples
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 | <!DOCTYPE html>
<html lang="en" xmlns:th="http://www.thymeleaf.org/">
<head th:fragment="head">
<meta charset="UTF-8"/>
<title th:text="${pageTitle}"></title>
</head>
<body>
<h1 th:replace = "fragments :: styledHeader"></h1>
<!-- Specific template code here... -->
<p th:replace = "fragments :: linkList"></p>
</body>
|
When the code runs, the h1
element in line 9 will be replaced by the
styledHeader
fragment stored in the fragments.html
file. Also, the
p
element in line 13 will be replaced by the <hr>
and three <a>
elements defined in the linkList
fragment.
Code along with the following video to practice using fragments in your templates:
Note
The starter code for this video is found at the form2 branch. of the coding-events-demo
repo.
The final code presented in this video is found on the fragments branch. As always, code along to the
videos on your own coding-events
project.
Remember that the summary text for the fragment
and replace
keywords
supports the video and is NOT intended as a replacement.
Question
Given our code fragment in fragments.html
:
1 2 3 4 5 6 | <th:block th:fragment = "linkList">
<hr>
<a href = "https://www.launchcode.org">LaunchCode</a> <br/>
<a href = "https://www.lego.com">Play Well</a> <br/>
<a href = "https://www.webelements.com">Other Building Blocks</a>
</th:block>
|
Which of the following would place the linkList
fragment inside a
<div>
element in the template?
<div th:replace = "fragments :: linkList"></div>
<div>${th:replace = "fragments :: linkList"}</div>
<div><p th:replace = "fragments :: linkList"></p></div>
<p><div th:replace = "fragments :: linkList"></div></p>
Bonus Question
Research th:remove
to answer this question. Which of the following does
NOT remove the wrapper tag but does eliminate all of its children.
th:remove = "all"
th:remove = "body"
th:remove = "tag"
th:remove = "all-but-first"
th:remove = "none"