Utiliser Fragments dans Thymeleaf

View more Tutorials:

1- Qu'est-ce que Fragment ?

Un Fragment fait partie d'un Template. Thymeleaf vous permet d'importer des fragments de ce Template dans un autre Template. Il existe de nombreuses façons d'identifier un Fragment. Par exemple :
  • Sélectionnez toutes les étiquettes (tag) avec l'attribut (attribute) th:fragment="search-fragment".
  • Séléctionnez l'étiquette par ID.
  • Sélectionnez toutes les étiquettes par Css-class.
  • ....
L'important, lorsque vous voulez importer un Fragment d'un Template, c'est que vous devez décrire sa position.
La syntaxe pour décrire la position d'un Fragment d'un  Template :

~{/path-to-template/template-name :: selector}
Si vous voulez décrire la position de  Fragment d'un  Template courant il est possible d'utiliser une syntaxe plus concise :
~{:: selector}

~{this :: selector}

~{templatename: fragmentname}  (th:fragment)

Sélectionnez un  fragment par nom.

~{templatename: tagname}  (Tag Name)

Choisissez un  fragment par le nom de l'étiquette.
Sélectionnez les sous-balises d'une étiquette. Par exemple, sélectionnez toutes les étiquettes  <script> situées dans les balises <header> :

~{templatename: #id}   (ID)

Sélectionnez le  fragment par la valeur de l'attribut (attribute) ID de l'étiquette.

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

Sélectionnez  fragment par  Css Class :

~{templatename}  (Everything)

Sélectionnez toutes dans  Template :

Other...

Autres exemples :
~{fragments/my-template :: #tagId/text() }

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

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

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

La fonction qui permet d'importer des fragment d'un Template à un autre Template est vraiment géniale. Il permet de faciliter la conception de l'interface du site web. Prenons l'exemple suivant :
Dans cet exemple, le fichier  my-template.html contient plusieurs  fragment, que autres  Template peuvent importer pour utiliser.
/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>
Le fichier  my-page.html est un  Template, il importe quelques  fragment du  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>
Le résultat que vous recevez :
(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 va insérer Fragment pour agir comme l'enfant de l'étiquette (Target tag).
  • th:replace remplacera l'étiquette cible par Fragment.
  • th:include va insérer l'enfant de Fragment pour agir comme l'enfant de l'étiquette cible.
Remarque : L'attribut (attribute) th:include est utilisé dans  Thymeleaf 2, et il ne sera pas utilisé dans le version  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>
Résultat :
(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 with parameters

Un  fragment sera comme une fonction (function) s'il ajoute des paramètres et heureusement le  Thymeleaf soutient pour le faire.

Paramètres explicites :

Si vous déclarez un  fragment et énumérez explicitement sa liste de paramètres. Ces paramètres seront des paramètres obligatoires comme dans l'exemple suivant : 
<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>
Ajoutez des paramètres lorsque vous appelez 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>

Paramètres implicites

Vous pouvez créer un  fragment avec des paramètres implicites. Il s'agit de paramètres facultatifs, comme dans l'exemple suivant :  
<!-- 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>
Appelez  fragment qui contient des paramètres implicites.
<div th:replace="~{fragments/my-template2 :: greeting(title='Mr.', name = 'Tom') }"></div>    
    
<div th:replace="~{fragments/my-template2 :: greeting }"></div>   

4- th:assert

L'attribut (attribute) th:assert vous aide à évaluer une expression, ou plusieurs expressions (Expressions séparées par des virgules). Si toutes les expressions sont évaluées comme étant true (vraie), il n'y aura aucun problème, si une expression est évaluée comme false (fausse), une exception sera levée.
<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: