dimanche 29 décembre 2019

Les formulaires avec thymeleaf

Dans un précédent tutoriel, le moteur de thymeleaf a été présenté rapidement. Nous allons ici présenté comment utiliser un formulaire avec ce moteur de template.

Nous verrons deux façon d'appréhender les formulaires.

La sauvegarde est complètement différentes.

Le formulaire est utilisé pour la sauvegarde d'un utilisateur.

Le modèle est

public class User {

    private String firstname;
    private String lastname;

    private boolean enabled;
   
    private String userTypeId;

    ...
}

public class UserType {

    private Long id;
    private String type;

    ...
}

Le code pour afficher le formulaire est

@GetMapping(value = {"/userform"})
    public String getUserForm(Model model) {

        List<UserType> userTypes = new ArrayList<>();

        UserType userType1 = new UserType();
        userType1.setId(1l);
        userType1.setType("Admin");

        UserType userType2 = new UserType();
        userType2.setId(2l);
        userType2.setType("Standard");

        UserType userType3 = new UserType();
        userType3.setId(3l);
        userType3.setType("Invité");


        userTypes.add(userType1);
        userTypes.add(userType2);
        userTypes.add(userType3);


        model.addAttribute("user", new User());
        model.addAttribute("userTypes", userTypes);


        return "formuser";
    }


La page html ne fait qu'ajouter quelques marqueurs

<!DOCTYPE html>
<html>
    <head th:include="fragments/head :: HeadCss"/>
    <body>
        <div th:replace="fragments/top-menu :: TopMenu('user')"/>

        <h3>Form User</h3>

        <div id="main" class="container-fluid">

            <form action="#" th:action="@{/userform}" th:object="${user}" method="post">

                <div class="form-group row">
                    <label th:for="firstname" class="col-sm-2 col-form-label" >Prénom</label>
                    <div class="col-sm-10">
                        <input type="text" class="form-control" id="firstname" th:placeholder="#{user.firstname.placeholder}" th:field="*{firstname}" />
                    </div>
                </div>

                <div class="form-group row">
                    <label th:for="lastname" class="col-sm-2 col-form-label" >Nom</label>
                    <div class="col-sm-10">
                        <input type="text" class="form-control" id="lastname" th:placeholder="#{user.lastname.placeholder}" th:field="*{lastname}" />
                    </div>
                </div>

                <div class="form-group row">
                    <label th:for="userTypeId" class="col-sm-2 col-form-label" >Type</label>
                    <div class="col-sm-10">
                        <select id="type" th:field="*{userTypeId}">
                            <option th:each="userType : ${userTypes}" th:value="${userType.id}" th:text="${userType.type}"></option>
                        </select>
                    </div>
                </div>

                <div class="form-group row">
                    <label th:for="enabled" class="col-sm-2 col-form-label">Actif</label>
                    <div class="col-sm-10">
                        <input type="checkbox" th:field="*{enabled}" />
                    </div>
                </div>

                <div class="form-group">
                    <div class="col-sm-12">
                        <div class="float-right">
                            <button type="submit" class="btn btn-primary">Sauvegarder</button>
                            <button type="button" id="resetButton" class="btn btn-primary">Reset</button>
                        </div>
                    </div>
                </div>

            </form>

        </div>

    </body>
</html>


Dans le controller, deux variables sont assignés aux modèles via ces lignes

     model.addAttribute("user", new User());
     model.addAttribute("userTypes", userTypes);


Dans le formulaire,

th:action sert à spécifier l'url où sera soumis le formulaire
th:object sert à spécifier l'objet où sera lié les données  soumises au formulaire

Les attributs de l'objet sont accessible th:field



La sauvegarde du système

   @PostMapping(value = {"/userform"})
    public String savUserForm(@ModelAttribute User user) {

        System.out.println(user.toString());

        //do want you want with value
        return "savingok";
    }


La deuxiême façon nécessite un peu de javascript, car le mapping devra être fait manuellement.

<form id="form">
    <div class="form-group row">
        <label for="firstname" class="col-sm-2 col-form-label" >Prénom</label>
        <div class="col-sm-10">
            <input type="text" class="form-control" id="firstname" th:placeholder="#{user.firstname.placeholder}"  />
        </div>
    </div>

    <div class="form-group row">
        <label for="lastname" class="col-sm-2 col-form-label" >Nom</label>
        <div class="col-sm-10">
            <input type="text" class="form-control" id="lastname" th:placeholder="#{user.lastname.placeholder}"  />
        </div>
    </div>

    <div class="form-group">
        <div class="col-sm-12">
            <div class="float-right">
                <button type="button" class="btn btn-primary" onclick="saveForm()" >Sauvegarder</button>
                <button type="button" class="btn btn-primary">Reset</button>
            </div>
        </div>
    </div>
</form>


Pour le javascript



<script type="text/javascript">
    function toJSONString( form ) {
        var obj = {};
        var elements = form.querySelectorAll( "input, select, textarea" );
        for( var i = 0; i < elements.length; ++i ) {
                    var element = elements[i];
                    var id = element.id;
                    var value = element.value;

                    if( id ) {
                        obj[ id ] = value;
                    }
        }

        return JSON.stringify( obj );
    }

    function saveForm() {
                var XHR = new XMLHttpRequest();
                XHR.open('POST', 'http://localhost:8080/userformrest');
                XHR.setRequestHeader("Content-Type", "application/json;charset=UTF-8");
                //JSON.stringify();

                var formElement = document.querySelector("form");
               
                var json = toJSONString(formElement);
               
                var formData = new FormData(formElement);

                XHR.send(json);

    }
</script> 

Le paramètre pour la sauvegarde est différent. Ce n'est plus l'annotation ModelAttribute qui est utilisé mais bien RequestBody.

    @PostMapping(value = {"/userformrest"})
    @ResponseBody
    public ResponseEntity savUserFormRest(@RequestBody User user) {

        System.out.println(user.toString());

        //do want you want with value
        return new ResponseEntity<>(HttpStatus.OK);
    }


Le code est disponible à https://github.com/marccollin/thymeleaf.

Aucun commentaire:

Enregistrer un commentaire