Usage of th: include, th: replace, th: insert, th: fragment in Thymeleaf

Preface

Postscript (2019/6/29)

th: include has been deprecated since thymeleaf 3.0. You pointed out in the comments. Thank you very much. There is no description that will be abolished at this time, but it seems better not to use th: include.

What is Thymeleaf?

Let's do Spring, which is a Java framework! If so, the most commonly used View template is Thymeleaf.

With this Thymeleaf, you can also create a template file for each part, and load it using th: include, th: replace, or th: insert. When I was using it for the first time, th: include? Th: replace? Th: insert? Which should I use? Since it was something like that, I will summarize it.

environment

Prerequisite knowledge

Basic usage of th: include, th: replace, th: insert

Assuming you have the following partial view

part.html


<div id="children">
  part
</div>

In case of include, it will be added as a small element

include.html


<div id="parent" th:include="part">text</div>
<!--result-->
<div id="parent">
  <div id="children">
    part
  </div>
</div>

In case of replace, the elements are swapped

replace.html


<div id="parent" th:replace="part">text</div>
<!--result-->
<div id="children">
  part
</div>

In the case of insert, the element is inserted. The result is the same as include.

insert.html


<div id="parent" th:insert="part">text</div>
<!--result-->
<div id="parent">
  <div id="children">
    part
  </div>
</div>

There are the following methods to specify the template

templateName is the path from the template directories. In the following case, it will be components / part.

 templates
   └── components
         └── part.html

You can also specify this :: fragmentName or :: fragmentName, where this points to your own template.

Define multiple parts in html th: fragment

Definition example

fragment.html


<div id="fragment1" th:fragment="template1()">
  <span>template1</span>
</div>
<div id="fragment2" th:fragment="template2(text)">
You can also pass arguments
  <span th:text="${text}"></span>
</div>

Main subject

The operation was as follows for reading without using the above fragment. There is no difference between th: include and th: insert.

--th: include-> Add the loaded html to the small element --th: replace-> The element is replaced with the loaded html --th: insert-> Add the loaded html to the small element

Be careful when using fragments. The fragment to be used is the above definition example.

th: include and th: fragment

include.html


<div id="include" th:include="fragment::template1()">
  <span>text</span>
</div>
<!--result-->
<div id="include">
  <span>template1</span>
</div>

The inside of th: fragment is passed. Elements such as id when th: included remain. Therefore, you can use it as follows.

<div th:if=${isDisplay} th:include="fragment::template1()"></div>

It is more natural to display the parts themselves with the template on the parent side. The applied class is also reflected, so if you use it properly, you can reuse it properly as a component.

th: replace and th: fragment

replace.html


<div id="replace" th:replace="fragment::template1()"></div>
<!--result-->
<div id="fragment1">
  <span>template1</span>
</div>

The point to note is that it replaces the place where th: fragment is defined. The id and if defined on the th: replace side are not determined.

th: insert and th: fragment

insert.html


<div id="insert" th:insert="fragment::template1()"></div>
<!--result-->
<div id="insert">
  <div id="fragment1">
    <span>template1</span>
  </div>
</div>

The element of th: fragment is inserted. Since id remains like th: include, th: if etc. can be used.

Summary

When th: fragment is used, the output result differs between th: include and th: replace or th: insert. If you want to use elements such as class and th: if on the parent side, it is simpler to use th: insert. th: include has been deprecated since 3.0. As you can see from this, is it because it is difficult to understand the behavior when using fragment?

When do you use th: replace?

It can be used when creating a common template.

fragment.html


<head th:fragment="head(link, script)">
  <meta content="text/html; charset=UTF-8"/>
  <link href="common-link"/>
  <script src="common-src"/>
 
  <th:block th:if="${link != null}" th:include="${link}"></th:block>
  
  <th:block th:if="${script != null}" th:include="${script}"></th:block>
</head>
<!--User side-->
<html>
<head th:replace="fragment::head(~{head/link}, ~{head/sccript})">
  <link href="xxx"/>
  <link href="yyy"/>
  <script src="xxx"/>
  <script src="yyy"/>
</head>
<body>
  content
</body>
</html>
<!--result-->
<html>
<head>
  <meta content="text/html; charset=UTF-8"/>
  <link href="common-link"/>
  <script src="common-src"/>

  <link href="xxx"/>
  <link href="yyy"/>

  <script src="xxx"/>
  <script src="yyy"/>
</head>
<body>
  content
</body>
</html>

~ {} is a description method called a fragment expression. You can pass the actual tag content as an argument by using ~ {}. Since the part using th: replace is the head tag, you can see visually that the contents of the head tag are passed to the argument of fragment. We also use th: replace to force the fragment tag to head. Even if a stranger sees it, I wonder if I should write the contents of the head tag.

If it is include, the tag of fragment can be anything, so it seems that it is not necessary to say "the meta tag is included in the div ...". Since it is an html file in the first place, it should have the correct grammar as html without interpreting thymeleaf.

For those who do not want to worry about the details

By using th: block, I think that the scope of application should be the same as a result.

<th:block th:fragment="template()">
  <div>
    <span>template</span>
  </div>
</th:block>

Reference site

https://www.thymeleaf.org/doc/tutorials/3.0/usingthymeleaf_ja.html

Recommended Posts

Usage of th: include, th: replace, th: insert, th: fragment in Thymeleaf
Usage of th: include, th: replace, th: insert, th: fragment in Thymeleaf
Thymeleaf usage notes in Spring Boot
[Ruby] Classification and usage of loops in Ruby