在ajax更新

时间:2016-12-20 12:35:30

标签: ajax spring spring-boot thymeleaf modelattribute

我多次遇到以下问题:
我使用Controller将dto绑定到html表单(通过thymeleaf)。 请注意名为“invoiceDto”的模型

@RequestMapping(value = {"/create"}, method = RequestMethod.GET)
        public String create(Locale locale, Model model) throws Exception {
            final String login = this.getAuthentication().getCurrentApplicationUser();
            if (login == null || login.isEmpty())
                throw new Exception(this.getMessageSource().getMessage("label.findError", null, locale));

            final Future<Setting> setting = settingService.findFirst();
            final Future<ApplicationUserContactProjection> applicationUserContactProjection = applicationUserService.findByLogin(login);
            while (!setting.isDone() && !applicationUserContactProjection.isDone()) {
                Thread.sleep(100);
            }
            if (setting.get() == null || applicationUserContactProjection.get() == null)
                throw new Exception(this.getMessageSource().getMessage("label.error.findError",
                        null, locale));

            model.addAttribute("invoiceDto", new InvoiceDto(setting.get(), applicationUserContactProjection.get()));
            model.addAttribute("message", this.getMessageSource().getMessage("label.navigation.invoiceCreation", null, locale));
            return "invoice/create";
    }

我有一个html表单(百万美元生成),我使用上面的Java pojo dto和给定的modelattribute名称来填充我的输入字段。这是它的摘录。 重要的部分是id为“invoiceLineItems”的div,其中thymeleaf用lineItems片段替换其子div:

<form action="#" th:action="@{/invoice/newinvoice}" th:object="${invoiceDto}" role="form" method="post"
              class="form-signin" id="editInvoiceForm"
              accept-charset="utf-8">
        <div id="invoiceLineItems"><div th:replace="invoice/items :: lineItems"></div></form>

fragement包含以下内容 - 摘录它:

<td>
                    <input type="text"
                           th:field="*{items[__${index.index}__].lineItemTotalPrice}"
                           readonly
                           class="form-control" disabled
                           id="lineItemTotalPrice"/>
                </td>

给定pojo的摘录:

public class InvoiceDto implements Serializable {
        private Invoice invoice;
        private List<LineItem> items;

我像这样访问列表:

th:field="*{items[__${index.index}__].lineItemTotalPrice}"

问题:
我可以通过Ajax动态添加项目。我序列化整个表单(为方便起见)并调用控制器方法:

@RequestMapping(value = {"/newlineitem"}, method = RequestMethod.POST)
    public String newLineItem(@ModelAttribute("invoiceDto") InvoiceDto invoiceDto,
                              Model model)
            throws Exception {

        invoiceDto.addItem(new LineItem());
        final Future<InvoiceDto> calculatedInvoiceDto = invoiceService.calculateInvoice(invoiceDto);
        while (!calculatedInvoiceDto.isDone()) {
            Thread.sleep(100);
        }
        model.addAttribute("invoiceDto", calculatedInvoiceDto.get());
        return "invoice/dynamicitems :: lineItems";
    }

正如你所看到的,我让thymeleaf呈现一个特殊视图,因为在Ajax成功之后,spring无法正确设置modelattribute。
简而言之:在Ajax返回局部视图后,以下内容将引发异常:

th:field="*{items[__${index.index}__].lineItemTotalPrice}"

虽然这有效 - 请注意前缀invoiceDto:

th:field="*{invoiceDto.items[__${index.index}__].lineItemTotalPrice}"

问题: 这里有什么问题?
为什么在部分Ajax更新之后我必须在modelattribute的名称前加上前缀,而在第一次运行时我不必这么做?

感谢您的帮助!

编辑: 对于我的分享,如果页面通过ajax调用(到另一个弹簧控制器,修改invoiceDto)通过部分百万富翁html部分更新,那么春天“忘记”最初命名的表单modelattribute“invoiceDto”的方式。

因此,在控制器返回部分百万美元视图后,我必须访问带有前缀“invoiceDto”的字段,就好像没有invoiceDto属性一样。

再次感谢您的帮助!

1 个答案:

答案 0 :(得分:1)

如果我正确理解了您的问题,则您尝试在没有活动对象时使用*{}表示法。当ajax方法仅返回“ lineItems”片段时,Thymeleaf无法知道它属于带有th:object的表单。

我猜最好的解决方案是返回整个表单,然后在js中提取lineItems。 或者也许完全摆脱th:object(仅在您想显示验证错误的情况下才方便)。