Your browser doesn't support the features required by impress.js, so you are presented with a simplified version of this presentation.

For the best experience please use the latest Chrome, Safari or Firefox browser.

Introduction

Utilisation avec Spring

IndexController.java
@Controller
public class IndexController {

    @GetMapping(value = "/")
    public String index(final ModelMap model) {
        model.put("nom", "IPI");
        return "index";
    }

}
index.html
<html lang="en" xmlns:th="http://www.thymeleaf.org">
  <head>
      <title>Thymeleaf</title>
  </head>
  <body>
  <h1>Hello <span th:text="${nom}"></span> !</h1>
  </body>
</html>

Affichage

  • Affichage dans une balise HTML
  • Affichage inline
  • Attributs HTML

Balise HTML

@Controller
public class IndexController {

    @GetMapping(value = "/")
    public String index(final ModelMap model) {
        model.put("nom", "IPI");
        model.put("htmlText", "How are <strong>you</strong> ?");
        model.put("otherText", "Have a nice day !");
        return "index";
    }

}
<html lang="en" xmlns:th="http://www.thymeleaf.org">
  <head>
      <title>Thymeleaf</title>
  </head>
  <body>
  <h1>Hello <span th:text="${nom}">World</span> !</h1>
  <p th:utext="${htmlText}"></p>
  <p data-th-text="${otherText}"></p>
  </body>
</html>

Affichage Inline

@Controller
public class IndexController {

    @GetMapping(value = "/")
    public String index(final ModelMap model) {
        model.put("nom", "IPI");
        model.put("htmlText", "How are <strong>you</strong> ?");
        return "index";
    }

}
<html lang="en" xmlns:th="http://www.thymeleaf.org">
  <head>
      <title>Thymeleaf</title>
  </head>
  <body>
  <h1>Hello [[${nom}]] !</h1>
  <p>[(${htmlText})]</p>
  <p th:inline="none">[[crochets]] non interprétés!</p>
  </body>
</html>

Attributs HTML

@Controller
public class IndexController {

    @GetMapping(value = "/")
    public String index(final ModelMap model) {
        model.put("message", "Hello");
        model.put("nom", "IPI");
        model.put("htmlText", "How are <strong>you</strong> ?");
        return "index";
    }

}
<html lang="en" xmlns:th="http://www.thymeleaf.org">
  <head>
      <title>Thymeleaf</title>
  </head>
  <body>
  <input value="Hi" th:attr="value=${message}" />
  <input value="World" th:value="${nom}" />
  <input th:attr="placeholder=${nom},value=${nom}" />
  <a th:href="@{/sayHello(nom=${nom})}">Lien 1</a>
  <!-- générera le lien vers /sayHello?nom=IPI-->
  <a th:href="@{/sayHello2/{message}}">Lien 2</a>
  <!-- générera le lien vers /sayHello2/Hello-->
  </body>
</html>

Expressions et objets

  • Objets Web Context
  • Objets utilitaires
  • Expressions simples et litérales
  • Opérations, comparaisons et conditions

Objets Web context

@Controller
public class IndexController {

  @Autowired
  ServletContext context;

  @GetMapping(value = "/say")
  public String index(final ModelMap m, 
    HttpSession s, HttpServletRequest r) {
    m.put("foo", "Hello");
    s.setAttribute("bar", "World");
    context.setAttribute("foobar", "IPI");
    //ou
    r.getServletContext().setAttribute("foobar", "IPI");
    return "index";
  }
}
localhost:8080/say?msg=Hey
<span th:text="${#request.getAttribute('foo')}">Hello</span>

<span th:text="${#request.getParameter('msg')}">Hey</span>
<span th:text="${param.msg}">Hey</span>
<span th:text="${param.msg[0]}">Hey</span>

<span th:text="${#request.getRequestURI()}">say</span>

<span th:text="${#session.getAttribute('bar')}">World</span>
<span th:text="${session.bar}">World</span>
<span th:text="${#session.id}">BA7CD710FE9610F1CEF5174DFB3C04AE</span>

<span th:text="${#servletContext.getAttribute('foobar')}">IPI</span>
<span th:text="${application.foobar}">IPI</span>
<span th:text="${#servletContext.getServerInfo()}">Tomcat/9.0.36</span>

Objets utilitaires

#application.properties
message.hello=Hello
message.hello2=Hi
@Controller
public class IndexController {
  @GetMapping(value = "/say")
  public String index(final ModelMap m) {
    m.put("now", LocalDate.now());
    m.put("codePostal", 7600);
    m.put("prix", 1500);
    m.put("reduction", 0.1012);
    m.put("liste", Arrays.asList(5,3,9,6));
    return "index";
  }
}
localhost:8080/say?name=World
<span th:text="${#messages.msg('message.hello')}">Hello</span>
<span th:text="${#messages.msg('message.hello2', param.name)}">Hello</span>

<span th:text="${#temporals.format(now, 'dd/MM/YYYY')}"></span>

<span th:text="${#strings.defaultString(notDefined,'Non renseigné')}">Non renseigné</span>
<span th:text="${#strings.containsIgnoreCase(param.name,'or')}">true</span>
<span th:text="${#strings.toUpperCase(param.name)}">WORLD</span>

<span th:text="${#numbers.formatInteger(codePostal,5)}">07600</span>
<span th:utext="${#numbers.formatCurrency(prix)}">1 500,00 €</span>
<span th:utext="${#numbers.formatPercent(reduction, 1, 0)}">10 %</span>

<span th:utext="${#lists.size(liste)}">4</span>
<span th:utext="${#lists.sort(liste)}">[3, 5, 6, 9]</span>

Expressions simples et litérales

localhost:8080/say?name=World
<span th:text="'Hello ' + ${param.name}">Hello World</span>
<span th:text="|Hello ${param.name}|">Hello World</span>
<span th:text="25 * 2">50</span>
<span th:text="false == true">false</span>
<span th:text="${param.message} == null">true</span>

Opérations, comparaisons et conditions

@Controller
public class IndexController {
  @GetMapping(value = "/")
  public String index(final ModelMap m) {
    m.put("montant", 100.0);
    m.put("tva", 20);
    return "index";
  }
}
<span th:text="${montant} * (100 + ${tva}) / 100">120</span>
<span th:text="${montant} % 3">1</span>
<span th:text="${montant} - 10">90</span>
<span th:text="${tva} &gt; 10">true</span>
<span th:text="${montant} &lt; 150">true</span>
<span th:text="${tva} == null ? 'HT'">HT</span>
<span th:text="${tva} == 20 ? 'TTC' : 'HT'">TTC</span>
<span th:text="${montant} ?: 'Montant non renseigné'">Montant non renseigné</span>
<span th:text="${montant} ?: _">Montant non renseigné</span>

Conditions et itérations

  • Conditions
  • Itérations

Conditions

@Controller
public class IndexController {
  @GetMapping(value = "/")
  public String index(final ModelMap m) {
    m.put("idProduit", 4);
    m.put("typeProduit", "book");
    m.put("items", Arrays.asList("Item 1", "Item 2"));
    return "index";
  }
}
<a href="/saveExisting" th:if="${idProduit} != null">Enregistrer</a>
<a href="/saveNew" th:unless="${idProduit}">Créer</a>
<a href="/details" th:if="${not #lists.isEmpty(items)}">Voir le détail</a>

<div th:switch="${typeProduit}">
  <span th:case="book">Livre</span>
  <span th:case="dvd">DVD</span>
  <span th:case="*">Autre</span>
</div>
<!-- Produira l'affichage suivant -->
<a href="/saveExisting">Enregistrer</a>
<a href="/details">Voir le détail</a>
<div>
  <span>Livre</span>
</div>

Itérations

@Controller
public class IndexController {
  @GetMapping(value = "/")
  public String index(final ModelMap m) {
    String[] typesProduits = new String[{"DVD", "Livre", "Autre"}];
    m.put("typesProduit", typesProduits);
    m.put("items", Arrays.asList("Item 1", "Item 2", "Item 3"));
    return "index";
  }
}
<ul th:each="item : ${items}">
  <li th:text="${item}"></li>
</ul>
<div th:each="typeP : ${typesProduit}">
  <a th:href="@{/typesProduits(type=${typeP})">${typeP}</a>
</div>
<!-- Produira l'affichage suivant -->
<ul>
  <li>Item 1</li>
  <li>Item 2</li>
  <li>Item 3</li>
</ul>
<div>
  <a href="/typesProduits?type=DVD">DVD</a>
  <a href="/typesProduits?type=Livre">Livre</a>
  <a href="/typesProduits?type=Autre">Autre</a>
</div>

Les fragments

  • Inclusion
  • Fragments paramétrés
  • Autres fonctionnalités

Inclusion de fragments

                  <!-- Template common.html -->
<html xmlns:th="http://www.thymeleaf.org">
  <body>
    <div class="nav-div" th:fragment="menu">
      <ul class="nav">
        <li class="nav-item">
          <a class="nav-link" href="#">Accueil</a>
        </li>
        ...
      </ul>
    </div>
    <div th:fragment="tab">...</div>
    <div class="footer" th:fragment="footer">
      &copy; Copyright 2020 Tous droits réservés
    </div>
  </body>
</html>
                
                  <!-- Autre template -->
<html xmlns:th="http://www.thymeleaf.org">
  <body>
    <div class="container"th:insert="common :: menu"></div>
    ...
    <div class="container" th:replace="common :: footer"></div>
  </body>
</html>
<!-- Donnera -->
<html>
<body>
  <div class="container">
    <div class="nav-div">
      <ul class="nav">...</ul>
    </div>
  </div>
  ...
  <div class="footer">&copy; Copyright 2020 Tous droits réservés</div>
</body>
</html>
                

Fragments paramétrés

                  <!-- Template common.html -->
<html xmlns:th="http://www.thymeleaf.org">
<body>
  <div th:fragment="menu(title, elements)">
    <h3 th:text="${title}"></h3>
    <ul th:each="elem : ${elements}" class="nav">
      <li class="nav-item"><a href="#">${elem}</a></li>
    </ul>
  </div>
</body>
</html>
              @Controller
public class IndexController {
  @GetMapping(value = "/")
  public String index(final ModelMap m) {
    m.put("listElem", Arrays.asList("Accueil", "A propos"));
    return "index";
  }
}
                  <!-- Autre template -->
<html xmlns:th="http://www.thymeleaf.org">
  <body>
    <div th:insert="common :: menu('Menu', ${listElem})"></div>
  </body>
</html>
<!-- Donnera -->
<html>
<body>
  <div>
    <h3>Menu</h3>
    <div class="nav-div">
      <ul class="nav">
        <li class="nav-item"><a href="#">Accueil</a></li>
        <li class="nav-item"><a href="#">A propos</a></li>
      </ul>
    </div>
  </div>
</body>
</html>
                

Autres fonctionnalités

  • Flexible Layouts
  • Suppression de fragments
  • Héritage de fragments