Юрий Яхница
Юрий Яхница

Reputation: 427

How to select Object from Thymeleaf form?

I am trying to build a form with different type of objects in it.

Simple objects, like String or Integer I get with no problems using thymeleaf "select" tag from HTML, but when I want to get some more complex object I always get null object in POST request.

This is my code:

Form:

import javax.validation.constraints.Min;
import javax.validation.constraints.NotNull;
import javax.validation.constraints.Size;

public class PersonForm {

    @NotNull
    @Size(min=2, max=30)
    private String name;

    @NotNull
    @Min(18)
    private Integer age;

    private String type;

    @NotNull
    private Address address;

    public String getName() {
        return this.name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public Integer getAge() {
        return age;
    }

    public void setAge(Integer age) {
        this.age = age;
    }

    public String getType() {
        return type;
    }

    public void setType(String type) {
        this.type = type;
    }

    public String toString() {
        return "Person(Name: " + this.name + ", Age: " + this.age + ")";
    }

    public Address getAddress() {
        return address;
    }

    public void setAddress(Address address) {
        this.address = address;
    }
}

Address:

public class Address {
    String city;
    Integer code;

    public Address(String city, Integer code) {
        this.city = city;
        this.code = code;
    }

    public String getCity() {
        return city;
    }

    public void setCity(String city) {
        this.city = city;
    }

    public Integer getCode() {
        return code;
    }

    public void setCode(Integer code) {
        this.code = code;
    }

}

Controller:

import javax.validation.Valid;
import java.util.ArrayList;
import java.util.List;

@Controller
public class PersonController implements WebMvcConfigurer {


    @Override
    public void addViewControllers(ViewControllerRegistry registry) {
        registry.addViewController("/results").setViewName("results");
    }

    @GetMapping("/")
    public String showForm(PersonForm personForm, Model model) {
        List<String> types = new ArrayList<>();
        types.add("Male");
        types.add("Female");
        types.add("Alian");
        types.add("Non Human");

        List<Address> addresses = new ArrayList<>();
        addresses.add(new Address("Kyiv",01000));
        addresses.add(new Address("Hayvoron",26300));

        model.addAttribute("cities",addresses);
        model.addAttribute("allTypes",types);
        return "form";
    }

    @PostMapping("/")
    public String checkPersonInfo(@Valid PersonForm personForm, BindingResult bindingResult) {


        PersonForm person = personForm;
        if (bindingResult.hasErrors()) {
            return "form";
        }

        return "redirect:/results";
    }
}

And a simple HTML file, with two dropdown lists. The list with "String type" parameter works well, but the parameter "Address address" doesn't work well.

<html xmlns:th="http://www.thymeleaf.org">

<body>
<!--/*@thymesVar id="personForm" type="com.yurets_y.weblibrary.entity.PersonForm"*/-->
<form action="#" th:action="@{/}" th:object="${personForm}" method="post">
    <table>
        <tr>
            <td>Name:</td>
            <td><input type="text" th:field="*{name}" /></td>
            <td th:if="${#fields.hasErrors('name')}" th:errors="*{name}">Name Error</td>
        </tr>
        <tr>
            <td>Age:</td>
            <td><input type="text" th:field="*{age}" /></td>
            <td th:if="${#fields.hasErrors('age')}" th:errors="*{age}">Age Error</td>
        </tr>
        <tr>
            <td>
                Gender
            </td>
            <td>
                <select th:field="*{type}">
                    <option th:each="type : ${allTypes}"
                            th:value="${type}"
                            th:text="${type}">Wireframe</option>
                </select>
            </td>
        </tr>
        <tr>
            <td>
                Address
            </td>
            <td>
            <select  th:field="*{address}">
                <option th:each="city : ${cities}"
                        th:value="city"
                        th:text="${city.city}"

                >Address</option>
            </select>


        </td>
        <!--</tr>-->
        <tr>
            <td><button type="submit">Submit</button></td>
        </tr>
    </table>
</form>
</body>
</html>

Is there any way to select some complex object in "select" form?

Upvotes: 2

Views: 8064

Answers (1)

J&#250;lio Falbo
J&#250;lio Falbo

Reputation: 1926

It is not possible because Thymeleaf will call .toString() method to set the value.

You can check this inspecting the element.

See the image

So, the best strategy is returning the id of the element for your Controller.

<select th:field="*{addressId}">
    <option th:each="city : ${cities}"
        th:value="${city.code}"
        th:text="${city.city}">
            Address
    </option>
</select>

Upvotes: 3

Related Questions