Reputation: 1593
I am developing a grocery store list web application. One feature should be (un)checking found/bought items on the list. Displaying all the values works fine. But when I check some checkboxes on some bought items and try to POST it afterwards the incomming @ModelAttribute
in the spring MVC controller is null (except the id).
I hope you can help me.
Here are my classes:
public class PurchaseList {
private Long id;
private List<PurchaseItem> purchaseItemList;
private DateTime purchaseDate;
private boolean done;
}
public class PurchaseItem {
private Long id;
private String purchaseItemName;
private PurchaseCategory purchaseCategory;
private PurchaseList purchaseList;
private boolean found;
}
The Controller:
@RequestMapping(value="/{id}", method=RequestMethod.POST)
public String postPurchaseList(@PathVariable(value="id") Long id, @ModelAttribute("purchaseList") PurchaseList purchaseList, Model model) {
List<PurchaseList> notDonePurchaseList = purchaseListService.getNotDonePurchaseList();
model.addAttribute("notDonePurchases", notDonePurchaseList);
purchaseListService.savePurchaseList(purchaseList);
return "purchaseList";
}
The Thymeleaf template
<form action="#" th:action="@{/purchaseList/{purchaseListId}/(purchaseListId=${purchaseList.id})}" th:object="${purchaseList}" method="post">
<table class="table table-bordered table-hover">
<thead>
<tr>
<td>Found</td>
<td>Item</td>
<td>Category</td>
</tr>
</thead>
<tr th:each="item,status : ${purchaseList.purchaseItemList}">
<td><input type="checkbox" th:checked="${item.found}" th:value="*{purchaseItemList[__${status.index}__].found}" /></td>
<td th:text="${item.purchaseItemName}"></td>
<td th:text="${item.purchaseCategory.categoryName}"></td>
</tr>
</table>
<input type="submit" value="Submit" id="submit" />
</form>
I know that I doesn't set the other values (only the found
property). Or is this the problem?
Best regards
Edit:
ArrayList
purchaseItemList. Now an empty ArrayList
is returned to the controller. Upvotes: 0
Views: 4009
Reputation: 43
Initialize the purchaseItemList in PurchaseList class.
public class PurchaseList {
private Long id;
private List<PurchaseItem> purchaseItemList=new ArrayList<>();
private DateTime purchaseDate;
private boolean done;
}
Give a input field an id like this.
<td><input type="checkbox" th:checked="${item.found}" th:value="* {purchaseItemList[__${status.index}__].found}" th:id='purchaseList.purchaseItemList[__${status.index}__].found'/></td>
Upvotes: 0
Reputation: 1593
I've found the problem and the solution.
I've seen in some tutorials and blog posts the usage of th:field=*{..}
but I didn't use it, because i trusted the Spring Tool Suite (it doesn't offer the th:field
attribute on autocomplete. Therefore I was sure that this attribute couldn't be used anymore. But I was wrong. I changed in my template code some of the *th:value=${..}
attributes to th:field=*{..}
as follows:
<form action="#" th:action="@{/purchaseList/{purchaseListId}/(purchaseListId=${purchaseList.id})}" th:object="${purchaseList}" method="post">
<input type="hidden" th:field="*{id}" />
<input type="hidden" th:field="*{purchaseDate}" />
<input type="hidden" th:field="*{done}" />
<table class="table table-bordered table-hover">
<thead>
<tr>
<td>Found</td>
<td>Item</td>
<td>Category</td>
</tr>
</thead>
<tr th:each="item,status : ${purchaseList.purchaseItemList}">
<td><input type="checkbox" th:checked="${item.found}" th:field="*{purchaseItemList[__${status.index}__].found}" th:id="${'purchaseList.purchaseItemList[__${status.index}__].found' + 'status.index'}"/></td>
<td th:text="${purchaseList.purchaseItemList[__${status.index}__].purchaseItemName}">
<input type="hidden" th:field="*{purchaseItemList[__${status.index}__].purchaseItemName}"
th:value="${purchaseList.purchaseItemList[__${status.index}__].purchaseItemName}"
th:id="${'purchaseList.purchaseItemList[__${status.index}__].purchaseItemName'}"
/>
</td>
<td th:text="${item.purchaseCategory.categoryName}">
<input type="hidden" th:field="*{purchaseItemList[__${status.index}__].purchaseCategory.categoryName}"
th:value="${purchaseList.purchaseItemList[__${status.index}__].purchaseCategory.categoryName}"
th:id="${'purchaseList.purchaseItemList[__${status.index}__].purchaseCategory.categoryName'}"
/>
</td>
</tr>
</table>
<input type="submit" value="Submit" id="submit" />
</form>
Now it works better. I get the "found" attributes in the controller. The other values are not set. But I think I messed up something within the hidden input fields.
Upvotes: 0