1

为什么服务器看不到我填写的复选框列表?

这个问题似乎在这里被问了很多次,但是每个请求者的细节是如此不同,以至于似乎每次都需要不同的答案。这是我的故事。

这些是我的数据承载类。报价包含过滤器属性中的过滤器对象列表:。

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]
}

简单控制器发送带有完全填充的 Offer 对象的 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]
}

该网页的复选框部分具有此功能。我使用 form:checkbox 而不是 form:checkboxes 因为我想使用表格,

[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]

显示的网页显示了三个过滤器复选框,仅填充了中间的复选框。

在此处输入图像描述

对于返回的列表,我希望服务器只获得中间的复选框,这正是我想要的。

以下是生成的复选框作为源的样子:

<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 处理程序中看不到复选框值?

感谢您的任何答案,

杰罗姆。

4

2 回答 2

0

复选框的值不能直接绑定到列表。

为了让它工作,你需要创建一个简单的 pojo 数据bean,它将在 jsp 中保存表单字段的值。并在该数据bean中绑定您需要声明int[] filterId的值,并且复选框的值将绑定在该数组中。

希望这对您有所帮助。

于 2013-02-12T05:14:46.023 回答
0

经过大量的网络研究和不同的调试会话,我想出了一个我可以接受的配置。

在我的控制器中,我提供了一个模型属性“filterList”,其中包含列表。“offerAttribute”是一个 Offer 对象,包含列表过滤器。

该视图具有以下顺序:

<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 值。未选中的包含空值。(也就是说,返回的过滤器列表是“稀疏的”。)如果用户只点击几个复选框,那么我必须解析返回的列表以找到那些被选中的。

一旦我知道选中过滤器的 ID 值,我就通过 Hibernate 获取它们中的每一个,将它们放入我重建的 Offer 对象中,然后将它们保存到数据库中。

我意识到我(当前)没有使用表单:复选框。但它有效,我在这里的时间很紧迫。也许我稍后会回来,看看 form:checkbox 可以为我做什么。

于 2013-02-14T21:44:56.243 回答