Commencer avec thymeleaf

Configuration

Pour commencer avec Thymeleaf, visitez [page de téléchargement officielle] (http://www.thymeleaf.org/download.html).

Dépendance Maven

<dependency> 
  <groupId>org.thymeleaf</groupId>
  <artifactId>thymeleaf</artifactId> 
  <version>3.0.1.RELEASE</version> 
</dependency>

Dépendance de Gradle

compile group: 'org.thymeleaf', name: 'thymeleaf', version: '3.0.1.RELEASE'

Exemple de configuration

À partir de la version 3.0, Thymeleaf ne prend en charge que la configuration Java.

public ViewResolver viewResolver() {
    ThymeleafViewResolver resolver = new ThymeleafViewResolver();
    resolver.setTemplateEngine(templateEngine());
    resolver.setCharacterEncoding("UTF-8");
    resolver.setContentType("text/html; charset=UTF-8");
    return resolver;
}

Dans la méthode viewResolver(), vous pouvez configurer par ex. encodage et type de contenu pour les vues. [plus d’informations][1]

public TemplateEngine templateEngine() {
    SpringTemplateEngine engine = new SpringTemplateEngine();
    engine.setTemplateResolver(templateResolver());
    return engine;
}

Dans templateEngine(), vous pouvez ajouter des dialectes personnalisés. Par exemple, pour ajouter le dialecte Spring Security, vous pouvez le faire comme ceci engine.addDialect(new SpringSecurityDialect());

public ITemplateResolver templateResolver() {
    SpringResourceTemplateResolver resolver = new SpringResourceTemplateResolver();
    resolver.setApplicationContext(applicationContext);
    resolver.setPrefix("/views/");
    resolver.setSuffix(".html");
    resolver.setTemplateMode(TemplateMode.HTML);
    resolver.setCharacterEncoding("UTF-8");
    return resolver;
}

Regardez setter pour le préfixe et le suffixe dans la méthode templateResolver(). Il indique à Thymeleaf que, chaque fois que le contrôleur renverra la vue, Thymeleaf recherchera ces noms HTML dans le répertoire webapp/views/ et ajoutera le suffixe .html pour vous.

Exemple

@RequestMapping(value = "/")
public String homePage() {
    return "foo/my-index";
}

Thymeleaf recherchera le code HTML nommé my-index.html dans le répertoire webapp/views/foo/. Selon l’exemple de configuration ci-dessus.

[1] : http://www.thymeleaf.org/apidocs/thymeleaf-spring4/2.0.20/org/thymeleaf/spring4/view/ThymeleafViewResolver.html

Utilisation des cases à cocher

Exemple de méthode dans le contrôleur

@RequestMapping(value = "/test")
public String showCheckbox(Model model) {
    boolean myBooleanVariable = false;
    model.addAttribute("myBooleanVariable", myBooleanVariable);
    return "sample-checkbox";
}

Afficher : sample-checkbox.html

<input 
      type="checkbox" 
      name="myBooleanVariable" 
      th:checked="${myBooleanVariable}"/>

N’utilisez pas th:name pour les cases à cocher, juste name

Soumission du formulaire

Objet de formulaire

package formSubmission;

public class Person {

    private String name;
    private int age;

    public String getName() {
        return name;
    }
    public void setName(String name) {
        this.name= name;
    }
    public int getAge() {
        return age;
    }
    public void setAge(int age) {
        this.age = age;
    }

}

Manette

package formSubmission;

import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.ModelAttribute;
import org.springframework.web.bind.annotation.PostMapping;

@Controller
public class FriendsController {

    @GetMapping("/friends")
    public String friendForm(Model model) {
        model.addAttribute("personForm", new Person());
        return "friendsForm";
    }

    @PostMapping("/friends")
    public String submissionResult(@ModelAttribute("personForm") Person person) {
        return "result";
    }

}

formulaireamis.html

<!DOCTYPE HTML>
<html xmlns:th="http://www.thymeleaf.org">
<head>
    <title>Friend form</title>
    <meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
</head>
<body>
    <h1>Friend Form</h1>
    <form th:action="@{/friends}" th:object="${personForm}" method="post">
        <p>Name: <input type="text" th:field="*{name}"/></p>
        <p>Age: <input type="number" th:field="*{age}"/></p>
        <p><input type="submit" value="Submit"/></p>
    </form>
</body>
</html>

résultat.html

<!DOCTYPE HTML>
<html xmlns:th="http://www.thymeleaf.org">
<head>
    <title>Submission result</title>
    <meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
</head>
<body>
    <h1>th:text="'My friend ' + ${personForm.name} + ' is ' + ${personForm.age} + ' years old'"</h1>
</body>
</html>

Soumission de formulaire Ajax avec Jquery

Pour soumettre un formulaire via Ajax avec Jquery :

    <div id="yourPanel" th:fragment="yourFragment">  
        <form id="yourForm" method="POST" 
              th:action="@{/actions/postForm}"
              th:object="${yourFormBean}">
        <div class="form-group">
            <label for="param1"></label>
            <input class="form-component" type="text" th:field="*{param1}" />
        </div>
        <div class="form-group">
            <label for="param2"></label>
            <input class="form-component" type="text" th:field="*{param2}" />
        </div>
        <div class="form-group">
            <label for="param3"></label>
            <input class="form-component" type="checkbox" th:field="*{param3}" />
        </div>

        <button type="submit" class="btn btn-success">Save</button>
        <a href='#' class="btn btn-default">Cancel</a>
    </form>
    </div>

<script th:inline="javascript">
    /*<![CDATA[*/
    $(document).ready(function () {
        /*[+
         var postUrl = [[@{/actions/postForm(
         additionalParam=${#httpServletRequest.getParameter('additionalParam')}
         )}]]; 
         +]*/
        $("#yourForm").submit(function (e) {
            e.preventDefault();
            $.post(postUrl,
                    $(this).serialize(),
                    function (response) {
                        var isErr = 'hasError';
                        // when there are an error then show error
                        if (response.indexOf(isErr) > -1) {
                            $("#yourPanel").html(response);
                        } else {
                            var formData = $("#yourForm").serializeArray(),
                                    len = formData.length,
                                    urlEnd = '';
                            for (i = 0; i < len; i++) {
                                urlEnd += formData[i].name + '=' + encodeURIComponent(formData[i].value) + '&';
                            }

                            /*[+
                             var urlReplacement = [[@{/another/page(
                             additionalParam=${#httpServletRequest.getParameter('additionalParam')}
                             )}]] + urlEnd;
                             +]*/

                            window.location.replace(urlReplacement);
                        }
                    }
            );
            return false;
        });
    });
    /*]]>*/
</script>

Classe YourFormBean :

@lombok.Getter
@lombok.Setter
@lombok.NoArgsConstructor
public class YourFormBean {
    private String param1;
    private String param2;
    private boolean param3;
}

Code contrôleur :

@RequestMapping(value = "/actions/postForm", method = RequestMethod.POST) 
public String saveForm(Model model, 
        @RequestParam("additionalParam") Integer additionalParam, 
        @Valid @ModelAttribute("yourFormBean") YourFormBean yourFormBean,
        BindingResult bindingResult,
        RedirectAttributes redirectAttributes) {
    if (bindingResult.hasErrors()) {
        model.addAttribute("hasError", true);
        return "your/template :: yourFragment";
    }
    redirectAttributes.addAttribute("additionalParam", additionalParam);
    
    return "redirect:/another/page";
}

Remplacer les fragments par ajax

Si vous souhaitez remplacer des parties de votre site Web, ajax est un moyen simple de le faire.

Le siteweb.html dont vous souhaitez remplacer le contenu en fonction de la valeur sélectionnée :

<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml"
  xmlns:th="http://www.thymeleaf.org">

    <head>
        <title>Index</title>
    </head>

    <body>
        <select id="selection">
            <option>Content 1</option>
            <option>Content 2</option>
        </select>

        <div id="replace_div">
            Content goes here
        </div>

        <!-- JQury from Google CDN -->
        <script src="https://ajax.googleapis.com/ajax/libs/jquery/3.1.1/jquery.min.js"></script>

        <script>
            $(document).ready(function () {

                //call function when page is loaded
                getContent();

                //set on change listener
                $('#selection').change(getContent);

                function getContent() {

                    //create url to request fragment
                    var url = /content/;
                    if ($('#selection').val() === "Content 1") {
                        url = url + "content1";
                    } else {
                        url = url + "content2";
                    }

                    //load fragment and replace content
                    $('#replace_div').load(url);
                }
            })
        </script>
    </body>
</html>

Et le content.html avec les fragments que vous souhaitez inclure en fonction de la valeur sélectionnée :

<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml"
      xmlns:th="http://www.thymeleaf.org">
    <head>
    </head>

    <body>
        <div th:fragment="content1">
            This is Content 1
        </div>

        <div th:fragment="content2">
            This is Content 2
         </div>
    </body>
</html>

Enfin, le Spring MVC ContentController.java :

@Controller
@RequestMapping("content")
public class ContentController {

    @RequestMapping("")
    public String loadContent() {
        return "website";
    }

    @RequestMapping("content1")
    public String getContent1() {
        return "content :: content1";
    }

    @RequestMapping("content2")
    public String getContent2() {
        return "content :: content2";
    }
}