Issue
I have the following domain object:
public class Pizza extends AbstractProduct {
public enum Size { SMALL, MEDIUM, LARGE }
private Size size;
private List<Ingredient> ingredients;
// Getters and setters
}
This object contains a list of Ingredient objects:
public class Ingredient {
public enum Type { SAUCE, VEGGIES, PROTEIN, CHEESE }
private int id;
private String name;
private Type type;
// Getters and setters
}
I want to pass Pizza object between 2 controllers.
Firstly, I retrieve Pizza object from pizza service and pass it to the view.
@Controller
@RequestMapping("/pizzas")
public class PizzaController {
@GetMapping("/{id}")
public String getPizzaInfo(@PathVariable int id, Model model) {
Pizza pizza = // Getting pizza
model.addAttribute("pizza", pizza);
return "pizza/pizza-info";
}
}
Then, user clicks on "Add to cart" button, sends POST request, and I receive this request in CartController.
@Controller
@RequestMapping("/cart")
public class CartController {
@PostMapping("/add-pizza")
public String addPizzaToOrder(@ModelAttribute Pizza pizza) {
// Order business logic
}
}
I use html hidden inputs to get data from Pizza object passed in PizzaController.
<form method="post" th:object="${pizza}" th:action="@{/cart/add-pizza}">
<input type="hidden" th:field="${pizza.id}" id="id">
<input type="hidden" th:field="${pizza.name}" id="name">
<input type="hidden" th:field="${pizza.price}" id="price">
<input type="hidden" th:field="${pizza.imageUrl}" id="img_url">
<label>
<select name="size">
<option th:each="size : ${T(pizzaonline.service.domain.Pizza.Size).values()}"
th:value="${size}" th:text="${size}"></option>
</select>
</label>
<button>Add to cart</button>
</form>
Everything works well except for one field - ingredients. I need something semantically equal to <input type="hidden" th:field="${pizza.ingredients}" id="ingredients">
to copy the ingredient list.
How can i do this?
Solution
If you want to do it the same way you're doing pizza, it would look like this:
<th:block th:each="ingredient, status: ${pizza.ingredients}">
<input type="hidden" th:field="*{ingredients[__${status.index}__].id}" />
<input type="hidden" th:field="*{ingredients[__${status.index}__].name}" />
<input type="hidden" th:field="*{ingredients[__${status.index}__].type}" />
</th:block>
You can also look at using the @SessionAttributes
attribute on your controller, and simply omit all the hidden fields. It will temporarily store the specified model attributes in the session and keep the value of the fields that are already specified.
Answered By - Metroids
Answer Checked By - Candace Johnson (JavaFixing Volunteer)