Search code examples
jqueryhtmlspringtwitter-bootstrapthymeleaf

Thymeleaf form always give null value to controller


i'm currently working on school project and I'm a bit lost. I have a form to add internship , an intership is define by a lot of elements like a name, content of internship , etc etc and the most important part for my problem, dates. In my form I use a datepicker to select my dates but when my object is retrieve to the "postmapping" method in my controler all of my dates have "null" value but I don't understand why.

Here is the code :

@Entity
@Table(name="stage")
@Where(clause="actif=true")
public class Stage{

    @Id
    @Column(name="id",nullable=false)
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private int id;

    //other attributes

    @DateTimeFormat(pattern = "dd-MM-yyyy") //I've try this but that change nothing
    @Column(name="date_candidature")
    private Calendar datecandidature;

    @Column(name="date_reponse")
    private Calendar datereponse;

    @Column(name="date_relance")
    private Calendar daterelance;

    //getters / setters / constructor

This model is link with table "stage"

DROP TABLE IF EXISTS `stage`;
CREATE TABLE IF NOT EXISTS `stage` (
  `id` int(100) NOT NULL AUTO_INCREMENT,
  `actif` tinyint(1) NOT NULL DEFAULT '1',
  `date_candidature` date DEFAULT NULL,
  `date_relance` date DEFAULT NULL,
  `date_reponse` date DEFAULT NULL,
  PRIMARY KEY (`id`)
) ENGINE=MyISAM AUTO_INCREMENT=16 DEFAULT CHARSET=utf8;

Then we have the controler's post method :

    @PreAuthorize("hasRole('ROLE_USER') or hasRole('ROLE_ADMIN')")
    @PostMapping(value={"/stage/add"})
    public ModelAndView stageAddPost(@ModelAttribute("stage") Stage stage, BindingResult errors, Model model) {
        System.out.println("Stage date candi : " + stage.getDatecandidature());
        System.out.println("Stage date relance : " + stage.getDaterelance());
        System.out.println("Stage date rep : " + stage.getDatereponse());
        stageService.saveOrUpdate(stage);
        ModelAndView mav = new ModelAndView("redirect:/");
        //mav.addObject("stage", stage);

        return mav;
    }

And then thymeleaf form :

<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml"
    xmlns:th="https://www.thymeleaf.org"
    xmlns:sec="https://www.thymeleaf.org/thymeleaf-extras-springsecurity5">
<head>
    <title>Ajout stage</title>

</head>
<body>



    <div th:replace="fragments/header :: head"></div>

    <!-- Page Content -->
    <div class="container pt-5">

        <form th:action="@{/stage/add}" th:object="${stage}" method="post">

                <input type="text" th:field="*{id}" hidden readonly>
                <input type="text" th:field="*{nouveau}" hidden readonly>
<!--                <input type="text" th:field="*{datederniereconnection}" hidden readonly> -->
<!--                <input type="text" th:field="*{datedernieremodification}" hidden readonly> -->
<!--                <input type="text" th:field="*{datecreation}" hidden readonly> -->
                <input type="text" th:field="*{actif}" hidden readonly>

            <div class="form-group row">
            <div class="col-md-4 mt-5">
                <label for="datecandidature">Date de candidature</label>
                <div class="input-group date">
                    <input type="text" class="form-control" autocomplete="off" th:id="datecandidature" th:name="datecandidature" th:value="*{datecandidature}"/>
                    <div class="input-group-append">
                        <span class="input-group-text"><i class="far fa-calendar-alt"></i></span>
                    </div>
                </div>
            </div>
        </div>
<!--            <div class="form-group"> -->
<!--                    <label for="inputNumeroRue">Date de candidature</label> <input type="date" -->
<!--                        class="form-control" id="inputNumeroRue" th:field="*{datecandidature}"> -->
<!--                    <p class="alert alert-warning" role="alert" th:if="${#fields.hasErrors('datecandidature')}" th:errors="*{datecandidature}"></p> -->

<!--            </div> -->

            <div class="col-md-4 mt-5">
                <label for="datereponse">Date de réponse</label>
                <div class="input-group date">
                    <input type="text" class="form-control" id="datereponse" autocomplete="off" th:field="*{datereponse}"/>
                    <div class="input-group-append">
                        <span class="input-group-text"><i class="far fa-calendar-alt"></i></span>
                    </div>
                </div>
            </div>

            <div class="col-md-4 mt-5">
                <label for="daterelance">Date de relance</label>
                <div class="input-group date">
                    <input type="text" class="form-control" id="daterelance" autocomplete="off" th:field="*{daterelance}"/>
                    <div class="input-group-append">
                        <span class="input-group-text"><i class="far fa-calendar-alt"></i></span>
                    </div>
                </div>
            </div>

            <button type="submit" class="btn btn-primary" value="Submit">Enregistrer</button>
        </form>

    </div>

    <div th:replace="fragments/footer :: foot"></div>
</body>
</html>

And the header fragment:

<!DOCTYPE html>
<html lang="fr" xmlns:th="http://www.thymeleaf.org">
<head>
<link rel="stylesheet" href="/webjars/bootstrap/css/bootstrap.min.css" />
<link rel="stylesheet" href="/webjars/bootstrap-datepicker/1.9.0/css/bootstrap-datepicker.css"/>
<link rel="stylesheet" href="/webjars/bootstrap-datepicker/1.9.0/css/bootstrap-datepicker.standalone.css"/>

<script src="/webjars/bootstrap/4.3.1/webjars-requirejs.js"></script>
<script type="text/javascript" src="/webjars/jquery/3.4.1/webjars-requirejs.js"></script>
<script type="text/javascript" src="/webjars/jquery/3.4.1/jquery.js"></script>

<script type="text/javascript" src="/webjars/popper.js/1.15.0/umd/popper.js"></script>
<script type="text/javascript" src="/webjars/bootstrap/4.3.1/js/bootstrap.min.js"></script>

<script src="https://kit.fontawesome.com/d72cc611fe.js" crossorigin="anonymous"></script>
<script src="/webjars/bootstrap-datepicker/1.9.0/js/bootstrap-datepicker.js"></script>
<script>
    var $j = jQuery.noConflict();
//          alert("HI"); // is it there yet?
             $j(document).ready(function() {
                    $j(".input-group.date").datepicker({
                        format: 'dd/mm/yyyy',
                        setDate: new Date(),
                        useCurrent: false,
                        autoclose: true,
                        pickerPosition: "bottom-left",
                        language: 'fr'
                    });
                  });   
</script>

<link href="/css/modern-business.css" rel="stylesheet">
</head>
<body>
    <div th:fragment="head">
        <nav class="navbar fixed-top navbar-expand-lg navbar-dark bg-dark fixed-top row align-items-center">
            <div class="container">
                <a class="navbar-brand col-lg-4" th:href="@{/}"><img th:src="@{/images/iutsd_ul.png}" width="80%" class="img-fluid" alt="Logo IUT et Unniversité de Lorraine"></a>
                <button class="navbar-toggler navbar-toggler-right" type="button" data-toggle="collapse" data-target="#navbarResponsive" aria-controls="navbarResponsive" aria-expanded="false" aria-label="Toggle navigation">
                    <span class="navbar-toggler-icon"></span>
                </button>
                <div class="collapse navbar-collapse col-lg-8" id="navbarResponsive">
                    <ul class="navbar-nav ml-auto">
                        <li class="nav-item">
                            <a class="nav-link" th:href="@{/}">Accueil</a>
                        </li>
                        <li class="nav-item">
                            <a class="nav-link" th:href="@{/a-propos}">A-propos</a>
                        </li>
                        <li sec:authorize="isAuthenticated() && hasRole('ROLE_ETUDIANT')"  class="nav-item" >
                            <a class="nav-link" th:href="@{/profil/mes-stages}">Mes stages</a>
                        </li>

                        <li sec:authorize="isAnonymous()">
<!--                            <a sec:authorize="isAuthenticated()" th:href="@{/logout}" class="btn btn-primary">Logout</a> -->
                            <a sec:authorize="isAnonymous()" th:href="@{/login}" class="btn btn-primary">Login</a>
                        </li>

                        <li sec:authorize="isAuthenticated()" class="nav-item dropdown no-arrow">
                            <a class="nav-link dropdown" href="#" id="userDropdown" role="button" data-toggle="dropdown" aria-haspopup="true" aria-expanded="false">
                                <i class="fas fa-user-cog"></i>
                            </a>
                            <div class="dropdown-menu dropdown-menu-right" aria-labelledby="userDropdown">
                                <a sec:authorize="hasAnyRole('ROLE_USER','ROLE_ADMIN')" class="dropdown-item" th:href="@{/profil}">Profil</a>
                            <div class="dropdown-divider"></div>
                                <a th:href="@{/logout}" class="dropdown-item">Logout</a>
                            </div>
                        </li>
                    </ul>
                </div>
            </div>
        </nav>
    </div>


</body>
</html>

Notice that I have del a lot of code to make it more readable for you. I hope someone can help me and sorry if I haven't explain correctly.

Edit : Change Calendar to Date work for "datereponse" and "daterelance" but doesn't for "datecandidature" cause of @DateTimeFormat(pattern = "dd-MM-yyyy")

edit 2 : @DatTimeFormat and add @Temporal(TemporalType.DATE) work correctly


Solution

  • try changing calendar to date & see if it working