johny.bravo
johny.bravo

Reputation: 77

How to bind user input with a BigDecimal object field in Spring MVC?

In my project I have a class with BigDecimal as one of its fields.

@Entity
public class Product {

    // ...
   
    @DecimalMin("0.01")
    private BigDecimal price;

    // ...
}

In thymeleaf I have a form with inputs for fields of this class and the one responsible for price is:

<form ...>
   <input type="number" step="any" th:field="*{price}">
</form>

When the @ModelAttribute is returned from this form, the price field of product is null. It used to work when the price was a double. How can I make this work? I thought of a workaround - to have this input as a @RequestParam and then initialize the Product.price using the double value 'manually' but is there some solution so that thymeleaf does that for me?

Upvotes: 0

Views: 2137

Answers (1)

Wim Deblauwe
Wim Deblauwe

Reputation: 26858

That should work. I just tested this using Spring Boot 2.3.0 as follows:

I am using a form data object, as directly using your entity for a form clutters reposibilities too much IMO:

import javax.validation.constraints.DecimalMin;
import java.math.BigDecimal;

public class ProductFormData {

    @DecimalMin("0.01")
    private BigDecimal price;

    public BigDecimal getPrice() {
        return price;
    }

    public void setPrice(BigDecimal price) {
        this.price = price;
    }
}

With a controller like this:

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;
import org.springframework.web.bind.annotation.RequestMapping;

@Controller
@RequestMapping("/product")
public class ProductController {

    @GetMapping
    public String product(Model model) {
        model.addAttribute("product", new ProductFormData());
        return "product";
    }

    @PostMapping
    public String doSaveProduct(@ModelAttribute("product") ProductFormData formData) {
        System.out.println("formData = " + formData.getPrice());

        return "redirect:/product";
    }
}

And the product.html template like this:

<!DOCTYPE html>
<html lang="en" xmlns:th="http:www.thymeleaf.org">
<head>
    <meta charset="UTF-8">
    <title>Product</title>
</head>
<body>
<h1>Product</h1>
<form th:action="@{/product}" th:object="${product}" method="post">
    <input type="number" step="any" th:field="*{price}">
    <button type="submit">submit</button>
</form>
</body>
</html>

When I type a number in the form and press 'submit', I see the value printed in the console.

Upvotes: 2

Related Questions