一尘不染

使用Spring动态表单的更好方法?

spring

我想知道的是,在使用SpringMVC和Spring表单时,是否有一种更简单/更好的方式来处理动态表单(通过js向dom添加表单项)?

具有具有多个LineItem的Invoice对象的图像。

public class Invocie {
    private List LineItems;

    public Invoice() {
        lineItems = ListUtils.lazyList(new ArrayList<LineItem>(), FactoryUtils.instantiateFactory(LineItem.class));
    }
}

显示属于我当前使用的发票的项目

<forEach items="${invoice.lineItems}" varStatus="i">
  <form:input path="lineItems[${i.index}].productName" />
</c:forEach>

要添加LineItem,我需要一些js来计算新索引并将其添加到DOM。删除LineItem时,我目前必须对所有索引重新编号,这是我要避免的部分,这可能吗?


阅读 477

收藏
2020-04-18

共2个答案

一尘不染

我发现,在JSP中添加/设置项目时,还必须使用GrowthList进行装饰,以避免出现一些错误。(还创建了一个自定义SpringList impl。基本上实现了双重修饰。)

lineItems = GrowthList.decorate(ListUtils.lazyList(new ArrayList<LineItem>(), FactoryUtils.instantiateFactory(LineItem.class)));

我同意。问题当然是删除项目。

你可以做的是在html中使用spring marker语法。因此,如果你使用javascript从列表中删除一项(例如,在索引2处),则可以使用以下标记该索引:

<input type="hidden" name="_lineItems[2]">

然后,在提交表单时,spring会看到标记并将lineItems 2放入一个空项目(基于惰性列表工厂),而不是忽略它。

2020-04-18
一尘不染

你可以使用以下内容

public class InvoiceController extends SimpleFormController {

    protected void initBinder(HttpServletRequest request, ServletRequetDataBinder binder) throws Exception {
        binder.registerCustomEditor(List.class, "lineItems", new CustomCollectionEditor(List.class)() {
            protected Object convertElement(Object lineItem) {
                LineItem li = (LineItem) lineItem;

                // StringUtils is a jakarta Commons lang static class
                return (StringUtils.isBlank(li.getProductName())) ? null : li;
            }

        });
    }

}

然后在onBind方法中,根据以下内容删除空引用:

protected void onBind(HttpServletRequest request, Object command, BindException bindException) throws Exception {
    Invoice invoice = (Invoice) command;

    invoice.getLineItems().removeAll(Collections.singletonList(null));
}  
2020-04-18