问题描述:

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:

  1. Initialized as suggested the ArrayList purchaseItemList. Now an empty ArrayList is returned to the controller.

网友答案:

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>

网友答案:

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.

相关阅读:
Top