2013-02-12 31 views
1

爲什麼服務器看不到我已填充的複選框列表?Spring MVC:未在POST後返回到控制器的複選框列表

這個問題似乎在這裏被問了很多次,但每個請求者的細節是如此不同,以至於每次都需要不同的答案。這是我的故事。

這些是我的數據承載類。要約包含過濾器屬性中的過濾器對象列表:

public class Offer implements Serializable { 

    @Id 
    @GeneratedValue(strategy=GenerationType.AUTO) 
    @Column(name="id") 
    private Long id = null; 

    @Column(name="title") 
    private String title = null; 
    [snip] 

    @ManyToMany(fetch=FetchType.EAGER) 
    @JoinTable(name = "offer_filter", 
     joinColumns = { @JoinColumn(name = "offer_id", nullable = false, updatable = false) }, 
     inverseJoinColumns = { @JoinColumn(name = "filter_id", nullable = false, updatable = false) }) 
    private List<Filter> filters; 

    [snip] 
} 

public class Filter implements Serializable { 

    @Id 
    @GeneratedValue(strategy=GenerationType.AUTO) 
    @Column(name="id") 
    private Long id; 

    @NotBlank 
    @Length(max=100) 
    @Column(name="text") 
    private String text; 

    [snip] 

    @Transient 
    private boolean owned = false; 

    [snip] 
} 

簡單的控制器發送offerEdit.jsp頁面,一個完全填充的Offer對象。該對象包含一個過濾器列表。由於擁有的屬性,三個過濾器中只有一個被預先檢查。這模擬了我最終的計劃,其中過濾器列表是整個宇宙,並且要約擁有的是子集。

請注意註釋,即要約包含過濾器列表進入網頁但未看到它回來。

public class OfferController { 
    [snip] 

    @RequestMapping(value = "/edit", method = RequestMethod.GET) 
    public String getEdit(@RequestParam("id") Long id, Model model, HttpSession session) { 
     Offer offerAttribute = offerService.get(id); 

     // At this point, offerAttribute.filters has three elements. 
     // Mockup -- tells web page that only the middle one of the three Filters should be checked. 
     List<Filter> filters = offer.getFilters(); 
     Filter filter = filters.get(1); 
     filter.setOwned(true); 

     model.addAttribute("offerAttribute", offerAttribute); 

     return "offer/offerEdit"; 
    } 

    @RequestMapping(value = "/edit", method = RequestMethod.POST) 
    public String postEdit(@RequestParam("id") Long id, @Valid @ModelAttribute("offerAttribute") Offer offerAttribute, BindingResult result, HttpSession session, Model model) { 

     // At this point, offerAttribute.filters is null. 
     if(result.hasErrors()) { 
      result.reject("offer.invalidFields"); 

      return "offer/offerEdit"; 
     } 

     offerAttribute.setId(id); 
     offerService.edit(offerAttribute); 

     return "redirect:/offer/list"; 
    } 

    [snip] 
} 

該網頁的複選框部分爲此。我使用形式:複選框重於形式:複選框,因爲我想用一個表,

[snip] 
<form:form modelAttribute="offerAttribute" method="POST" action="${saveUrl}"> 
    <table> 
     <tr> 
      <td></td> 
      <td><form:hidden path="id" /></td> 
     </tr> 

     <tr> 
      <td><form:label path="title">Title:</form:label></td> 
      <td><form:input path="title" size="80" /></td> 
      <td><form:errors path="title" cssClass="error" /></td> 
     </tr> 

    [snip] 
    </table> 

    <table> 
    </table> 

    <table> 
     <c:forEach items="${offerAttribute.filters}" var="filter"> 
      <tr> 
       <td><form:checkbox 
         path="filters" 
         label="${filter.text}" 
         value="${filter.id}" 
         checked="${filter.owned ? 'true' : ''}" /> 
       </td> 
      </tr> 
     </c:forEach> 
    </table> 
    [snip] 

顯示的網頁已經顯示三濾的複選框,與剛填充中間複選框

enter image description here

對於返回的列表,我希望服務器只能得到中間的複選框,這正是我想要的。

這裏是生成的複選框樣子源:

<table style="border: 1px solid; width: 100%; text-align:left;"> 
     <tr> 
      <td> 
       <input id="filters1" name="filters" type="checkbox" value="1"/> 
       <label for="filters1">Adults (18+) desired, please</label> 
       <input type="hidden" name="_filters" value="on"/> 
      </td> 
     </tr> 
     <tr> 
      <td> 
       <input id="filters2" name="filters" checked="true" type="checkbox" value="2"/> 
       <label for="filters2">Quiet audiences, please</label> 
       <input type="hidden" name="_filters" value="on"/> 
      </td> 
     </tr> 
     <tr> 
      <td> 
       <input id="filters3" name="filters" type="checkbox" value="4"/> 
       <label for="filters3">Filter Text First</label> 
       <input type="hidden" name="_filters" value="on"/> 
      </td> 
     </tr> 
</table> 

我的複選框被設置,並在HTML。要重申我的問題,

爲什麼在控制器的POST處理程序中看不到複選框的值?

感謝您的任何答案,

傑羅姆。

回答

0

經過大量的網絡研究和不同的調試過程,我想出了一個可以配置的配置。

在我的控制器中,我提供了一個「filterList」的模型屬性,其中包含List。 「offerAttribute」是一個Offer對象,包含List過濾器。

的觀點具有序列:

<table> 
    <c:forEach items="${filterList}" var="filter" varStatus="status"> 
     <tr> 
      <td><input type="checkbox" name="filters[${status.index}].id" 
       value="${filter.id}" 
       ${filter.owned ? 'checked' : ''} /> ${filter.text} 
      </td> 
     </tr> 
    </c:forEach> 
</table> 

當POST完成的ownerAttribute.filters名單只是只要創建該複選框原來filterList對象。選中的包含一個Filter.id值。未選中的包含null。 (也就是說,返回的過濾器列表是「稀疏的」。)如果用戶點擊了幾個複選框,那麼我必須解析返回的列表以找到所選的列表。

一旦我知道已簽入的過濾器的ID值,我通過Hibernate取得它們中的每一個,將它們放入我重構的Offer對象中,然後將它們保存到數據庫中。

我知道我沒有(當前)使用窗體:複選框。但它有效,我在這裏受到時間的限制。我稍後會回來,看看checkbox可以爲我做些什麼。

0

複選框的值不能直接綁定到List。

爲了得到這個工作,你需要創建一個簡單的pojo databean,它將在jsp中保存你的表單域的值。並在該數據庫中綁定您需要聲明int[] filterId的值,並且您的複選框的值將綁定到該數組中。

希望這可以幫助你。

+0

我的優惠類似乎是頁面的形式。當我沒有複選框列表時,我可以向數據庫添加和更新商品對象。我的問題是將複選框列表添加到聚會中。我可以添加一個int [] filterIds作爲@Transient,使複選框綁定到filterIds,然後通過服務器代碼處理結果。這是你在這裏建議的嗎? – 2013-02-12 12:47:01

+0

您是否使用javascript添加了新的複選框運行時? – 2013-02-12 12:58:55

+0

在這種情況下,您需要使用LazyList。 – 2013-02-12 13:00:45

相關問題