user3174967
user3174967

Reputation: 245

Thymeleaf, default values does not appear in my update form

I'm learning java and I'm practicing with thymeleaf. I made an little app where I have a list of persons (arraylist). I can add a person through a form but also edit a person from the list to update the person's firstname, lastname or birthdate through a form. Here is my problem I want when I edit a person to have its default values(firstname, lastname, bithdate) on the update form so that we can then change only the fields of interest. I have this code:

<!DOCTYPE HTML>
<html xmlns:th="http://www.thymeleaf.org">
   <head>
      <meta charset="UTF-8" />
      <title>Update Person</title>
      <link rel="stylesheet" type="text/css" th:href="@{/css/style.css}"/>
   </head>
   <body>
      <h1>Update a Person:</h1>

<!--       some tests I made to test if the value appears in the field -->
<!--        <input type="text"   name="id" th:value="${person.id}"  />  -->
<!--        <input type = "text" name = "firstName" th:value = "${person.firstName}" /> -->
<!--        <input type = "text" name = "sometext" th:value = "hello world" /> -->

      <form th:action="@{/updatePerson/{id}(id=${person.id})}"

              th:object="${person}" method="POST"> 
         First Name:
         <input type="text" th:field="*{firstName}"/>    
         <br/>
         Last Name:
         <input type="text" th:field="*{lastName}" />     
         <br/>
         Date of Birth (DD/MM/YYYY):
         <input type="date" th:field="*{birthDate}" />    
         <br/>
         ID:
         <input type="text" th:field="*{id}" />    
         <br/>
         <input type="submit" value="Update" />
     </form>    


      <br/>

      <!-- Check if errorMessage is not null and not empty -->

      <div th:if="${errorMessage}" th:utext="${errorMessage}"
         style="color:red;font-style:italic;">
         ...
      </div>

   </body>
</html>

None of my default values appears in the fields except for the id. Whether I use th:field="{id}" or name="id" th:value="${person.id}". Both synthax work but the others (ie: th:field="{firstName}" or name = "firstName" th:value = "${person.firstName}" same goes for lastname and birthdate), nothing works. I even tried th:value = "hello world" (commented in the above code), it does appear! So why my person firstname, lastname, bithdate don't appear? What is wrong? My person.list html works though:

<!DOCTYPE HTML>
<html xmlns:th="http://www.thymeleaf.org">
   <head>
      <meta charset="UTF-8" />
      <title>Person List</title>
      <link rel="stylesheet" type="text/css" th:href="@{/css/style.css}"/>
   </head>
   <body>
      <h1>Person List</h1>
      <a href="addPerson">Add Person</a>
      <br/><br/>
      <div>
         <table border="1">
            <tr>
               <th>First Name</th>
               <th>Last Name</th>
               <th>Date of Birth</th>
               <th>Edit</th>
               <th>Delete Name</th>
            </tr>
            <tr th:each ="person : ${list}">
               <td th:utext="${person.firstName}">...</td>
               <td th:utext="${person.lastName}">...</td>
               <td th:text="${#temporals.format(person.birthDate,'dd-MM-yyyy')}">...</td>
               <td><a th:href="@{/updatePerson/{id}(id=${person.id})}">
                        <span>
                            <img src="https://img.icons8.com/clouds/40/000000/edit.png">
                        </span>
                    </a></td>
               <td> 
                <form th:action="@{/deletePerson}" th:method="POST">                    
                    <input type = "hidden" name = "firstName" th:value = "${person.firstName}" />
                    <input type = "hidden" name = "lastName" th:value = "${person.lastName}" />
                    <input type = "hidden" name = "id" th:value = "${person.id}" />
                    <input type = "hidden" name = "birthDate" th:value = "${person.birthDate}" />
                    <button type = "submit" >
                        <span>
                            <img src="https://img.icons8.com/metro/26/000000/delete.png" />
                        </span>
                    </button>
                </form> 
               </td>
            </tr>
         </table>
      </div>

      <div>
        <form th:action="@{/changeDao}" th:method="POST">
            <select name="daoChoice">
                <option th:value="none" disabled>Choisissez votre Dao</option>
                <option id="jdbc" th:value="JDBC">Jdbc</option>
                <option id="memory" th:value="MEMORY" th:selected="${isMemory}">Memory</option>
            </select>
            <button type="submit">Valider</button>      
        </form>         
      </div>

      <div>
        <form th:action="@{/excelLoad}" th:method="GET">
            <button type="submit">Local Load</button>               
        </form>
      </div>

      <div>
        <form th:action="@{/UploadFile}" method="POST" enctype="multipart/form-data">
            <table>
               <tr>
                   <td><label>Upload and Add to the table</label></td>
                   <td><input type="file" th:value = "file" th:name="file" /></td>
               </tr>
               <tr>
                   <td><input type="submit" value="Upload" /></td>
               </tr>
            </table>
        </form>
      </div>

      <div>
        <form th:action="@{/exportToExcel}" th:method="POST">
            <button type="submit">Export to Excel</button>              
        </form>
      </div>

   </body>
</html>

Above my personList.html, person's firstName lastName and birthdate is printed correctly with this code:

<tr th:each ="person : ${list}">
               <td th:utext="${person.firstName}">...</td>
               <td th:utext="${person.lastName}">...</td>
               <td th:text="${#temporals.format(person.birthDate,'dd-MM-yyyy')}">...</td>

but why in my update form this is not working ?

I'm a newbie in java programming and also in thymeleaf (also newbie), so I'd really appreciate some explanations along some tips! thanks a lot!

Upvotes: 0

Views: 927

Answers (2)

user3174967
user3174967

Reputation: 245

I found it with another post where there was a simple explanation about the key/value pair in modelAddAttribute:

You can access variables value by ${key}. Example

model.addAttribute("key", value); 

Understanding that I found my mistake in my controller:

@RequestMapping(value = { "/updatePerson/{id}" }, method = RequestMethod.GET)
    public String showUpdatePersonPage(@PathVariable("id") int id, Person person, Model model) {

       person = personDao.findPerson(id);
       model.addAttribute("person", person);

        return "updatePerson";
    }

Before it was:

@RequestMapping(value = { "/updatePerson/{id}" }, method = RequestMethod.GET)
    public String showUpdatePersonPage(@PathVariable("id") int id, Person person, Model model) {

       person = personDao.findPerson(id);
       model.addAttribute("personToModify", person);

        return "updatePerson";
    }

And in my html the code was:

<form th:action="@{/updatePerson/{id}(id=${person.id})}"

          th:object="${person}" method="POST"> 
     First Name:
     <input type="text" th:field="*{firstName}"/>    
     <br/>
     Last Name:
     <input type="text" th:field="*{lastName}" />     
     <br/>
     Date of Birth (DD/MM/YYYY):
     <input type="date" th:field="*{birthDate}" />    
     <br/>
     ID:
     <input type="text" th:field="*{id}" />    
     <br/>
     <input type="submit" value="Update" />
 </form>    

So that was because the key name used "personToModify" couldn't be found in the html as the object name used wasn't properly named:

th:object="${person}"

Upvotes: 1

dsarrrrrr443
dsarrrrrr443

Reputation: 48

I can't see your Person class or controller but, for example, keeping it clean, you can create PersonForm class which can look like (might need to change Date)

import java.util.Date;

public class PersonForm {

    private String firstName;
    private String lastName;
    private Date birthDate;

    public PersonForm() {
    }

    public PersonForm(Person person) {
        this.firstName = person.getFirstName();
        this.lastName = person.getLastName();
        this.birthDate = person.getBirthDate();
    }

As you can see, it has fields which needs to populated and you set them in constructor, you can also apply validation annotations here if needed.

In your controller you would need to retrieve Person and using it, create and add PersonForm as model attribute. i.e.

@GetMapping("/person/edit/{id}") // you might not use id, might be username
public String editPerson(@PathVariable Long id, Model model) {
    Person person = personRepository.getOne(id); // or service
    PersonForm personForm = new PersonForm(person);
    model.addAttribute("personForm", personForm);
    // other stuff
    // return html
}

and then change th:object="${person}" to th:object="${personForm}"

Now all th:field="*{firstName}" and others should be populated.

Upvotes: 0

Related Questions