简体   繁体   English

如何使用Spring将列表中的输入值绑定到bean属性

[英]How to bind an input value in a list to a bean attribute with Spring

I need to bind an object with a list of objects as an attribute. 我需要将一个对象与一个对象列表绑定为一个属性。 It is a static list and it is created and partially filled in the Controller. 它是一个静态列表,已创建并部分填充到Controller中。 It is displayed correctly in the view, however the value in the input field is not set when the form is sent to the controller. 它在视图中正确显示,但是在将表单发送到控制器时未设置输入字段中的值。 I did some research and found several similar questions, however none of the proposed solutions worked for me. 我进行了一些研究,发现了几个类似的问题,但是所提出的解决方案均不适用于我。

edit.jsp edit.jsp

<c:forEach items="${priceConfigurationForm.priceList}" var="price" varStatus="priceStatus">
                    <tr>
                        <td>
                            <spring:bind path="priceConfigurationForm.priceList[${priceStatus.index}].country">
                                ${price.country}
                                <input type="hidden" name="<c:out value="${status.expression}"/>"
                                       id="<c:out value="${status.expression}"/>"
                                       value="<c:out value="${status.value}"/>"/>
                            </spring:bind>
                        </td>

                        <td>
                            <spring:bind path="priceConfigurationForm.priceList[${priceStatus.index}].amount">
                                <input type="text" name="price" value="${price.amount}"/>
                                <input type="hidden"
                                       name="<c:out value="${status.expression}"/>"
                                       id="<c:out value="${status.expression}"/>"
                                       value="<c:out value="${status.value}"/>"/>
                            </spring:bind>
                        </td>

                        <td>
                            <spring:bind path="priceConfigurationForm.priceList[${priceStatus.index}].currency">
                                ${price.currency}
                                <input type="hidden" name="<c:out value="${status.expression}"/>"
                                       id="<c:out value="${status.expression}"/>"
                                       value="<c:out value="${status.value}"/>"/>
                            </spring:bind>
                        </td>
                    </tr>
                </c:forEach>

Abstract from Controller populating the list: Controller填充列表的摘要:

@RequestMapping(value = "/price/create", method = RequestMethod.GET)
    public String toCreatePriceConfiguratioView(Model model) {

        log.info("::createPriceConfiguration: {}");

        final PriceConfigurationForm priceConfigurationForm = new PriceConfigurationForm();

        final List<PriceConfigurationForm.Price> prices = new ArrayList<>();
        for (Country country : Country.values()) {
            PriceConfigurationForm.Price price = new PriceConfigurationForm.Price();
            price.setAmount(100);
            price.setCountry(country.getCountryCode());
            price.setCurrency(country.getCurrency());
            prices.add(price);
        }

        priceConfigurationForm.setPriceList(prices);

        model.addAttribute("priceConfigurationForm", priceConfigurationForm);

        return "/secured/sources/onboarding/price/edit";
    }

Abstract from Controller for storing the list: 来自Controller的用于存储列表的摘要:

@RequestMapping(value = "/price/create", method = RequestMethod.POST)
    public String createPriceConfiguration(Model model, @ModelAttribute("priceConfigurationForm") @Valid PriceConfigurationForm priceConfigurationForm, BindingResult bindingResult, RedirectAttributes attributes) {

        log.info("::createPriceConfiguration {}", priceConfigurationForm);
        // TODO: Validate, before create

        /* transform form to domain object */
        PriceConfiguration configuration = PriceConfigurationForm.toPriceConfiguration(priceConfigurationForm);
        onboardingApi.createPriceConfiguration(configuration);

        attributes.addFlashAttribute("message", success("price configuration saved", priceConfigurationForm.getName()));
        return "/secured/sources/onboarding/price/index";
    }

Object: 宾语:

@Data
public class PriceConfigurationForm {

    private String name;

    private String description;

    private List<Price> priceList;

    private Map<String, Long> countryToPriceMap;

    public static PriceConfiguration toPriceConfiguration(PriceConfigurationForm form) {
        final PriceConfiguration pc = new PriceConfiguration();
        pc.setName(form.getName());
        pc.setDescription(form.getDescription());
        final Map<String, Long> prices = form.getPriceList().stream().collect(toMap(Price::getCountry, Price::getAmount));
        pc.setCountryToPriceMap(prices);
        return pc;
    }

    @Data
    public static class Price {
        private String country;
        private long amount;
        private String currency;
    }
}

This is example of how I sucessfully parsed nested objects in one project : 这是我如何在一个项目中成功解析嵌套对象的示例:

<c:forEach var="block" items="${newplaceform.blocks}" varStatus="counter">
        <fieldset data-block-order="${counter.index}" data-block-index="${counter.index}">
<c:if test='${block.type=="quizSingleAnswer"}'>
            <legend><s:message code='blocks.type.quizSingleAnswer'/> <a class="glyphicon glyphicon-move move-block pull-right" href="#"></a><a data-remove="block" class="glyphicon glyphicon-remove pull-right" href="#"></a><a data-reordering="up" class="glyphicon glyphicon-chevron-up pull-right" href="#"></a><a data-reordering="down" class="glyphicon glyphicon-chevron-down pull-right" href="#"></a></legend>
            <div class="form-group production-hide">
                <label class="col-sm-3 control-label">id:</label>
                <div class="col-sm-9"><input type="text" name="blocks[${counter.index}].id" value="${block.id}" data-row="blockId" data-disabled class="form-control"/></div>
            </div>
            <div class="form-group production-hide">
                <label class="col-sm-3 control-label">type:</label>
                <div class="col-sm-9"><input type="text" name="blocks[${counter.index}].type" value="${block.type}" data-disabled class="form-control"/></div>
            </div>
            <div class="form-group">
                <label class="col-sm-3 control-label"><s:message code='blocks.description'/>:</label>
                <div class="col-sm-9"><textarea class="form-control" name="blocks[${counter.index}].description" data-description rows="3">${block.description}</textarea></div>
            </div>
            <div class="row">
                <div class="col-sm-6">
                    <div class="col-sm-6 control-label">
                        <label class="inner-header"><s:message code='blocks.answers'/>:</label>
                    </div>
                    <div class="col-sm-6">
                        <div class="btn-group m-t-9">
                            <a class="btn btn-primary btn-xs" href="#" data-add-answer data-add-answer-block-index="${counter.index}"><i class="glyphicon glyphicon-plus"></i> <s:message code="blocks.add-answer" /></a>
                        </div>
                    </div>
                </div>
            </div>
            <div class="row quiz-answers" data-count-answer="${block.answers.size()}">
                <c:forEach var="answer" items="${block.answers}" varStatus="counterInner">
                    <div class="col-sm-6">
                        <fieldset>
                            <legend>
                                <div class="bootstrap-center">
                                    <span><s:message code="blocks.answerNo"/> ${counterInner.index+1}</span>
                                    <a data-remove="answer" class="glyphicon glyphicon-remove pull-right" href="#"></a>
                                </div>
                            </legend>
                            <div class="form-group production-hide">
                                <label class="col-sm-6 control-label">id:</label>
                                <div class="col-sm-6"><input type="text" name="blocks[${counter.index}].answers[${counterInner.index}].id" value="${answer.id}" data-row="answerId" data-disabled class="form-control"/></div>
                            </div>
                            <div class="form-group">
                                <label class="col-sm-6 control-label"><s:message code="blocks.answer"/>:</label>
                                <div class="col-sm-6"><input type="text" name="blocks[${counter.index}].answers[${counterInner.index}].text" value="${answer.text}" class="form-control"/></div>
                            </div>
                            <div class="form-group">
                                <div class="col-sm-6 col-sm-offset-6">
                                    <div class="checkbox">
                                        <label>
                                            <input type="checkbox" name="blocks[${counter.index}].answers[${counterInner.index}].right" value="true" ${answer.checked()}/>
                                            <s:message code="blocks.right"/>
                                        </label>
                                    </div>
                                </div>
                            </div>
                        </fieldset>
                    </div>
                </c:forEach>
            </div>

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM