如何在百里香叶形式上保留嵌套对象的属性

时间:2015-08-07 14:13:55

标签: spring-mvc thymeleaf

我有一个对象,我想动态加载表单字段。实例化和显示字段在显示时正常工作,但是,当我尝试提交表单时,除了用户提供的${field.value}之外,所有数据都将丢失。如何保留所有其他属性值?

这是生成表单对象的控制器方法:

@RequestMapping(method = RequestMethod.GET)
public String newFooForm(@AuthenticationPrincipal UserDetails user, @RequestParam("fooType") String fooType, @RequestParam("isTeam") Boolean isTeam, Model model) {
    Employee currentUser = getCurrentUser(user);
    List<FooFieldDefinition> fooFieldDefinitions = fooFieldDefinitionService.findByOrganizationalUnitIdAndIsTeam(currentUser.getOrgId(), isTeam);
    FooViewModel fooViewModel = new FooViewModel(currentUser, fooType, isTeam, fooFieldDefinitions);
    model.addAttribute("fooViewModel", fooViewModel);
    return "newFooForm";
}

在构造函数FooViewModel(currentUser, fooType, isTeam, fooFieldDefinitions)中调用以下代码段,其中填充了fooViewModel.fooFields:

fooFields = new ArrayList<>();
for (FooFieldDefinition fooFieldDefinition : fooFieldDefinitions) {
    fooFields.add(new FooField(fooFieldDefinition));
}

以下是表单的片段:

<form id="foo-form" action="#" th:action="@{/fooForms}" th:object="${fooViewModel}"
      method="post">
    <div th:each="fooField,iterationStatus  : *{fooFields}">
        <label th:text="${fooField.label}">Label</label>
        <input th:type="text" th:field="*{fooFields[__${iterationStatus.index}__].value}"/>
    </div>
    <div style="position: absolute; right: 20px; bottom: 20px;">
        <input class="btn btn-primary" id="save" type="submit" name="save" value="Save"/>
        <input class="btn btn-primary" id="submit" type="submit" name="submit" value="Submit"/>
    </div>
</form>

我知道fooField在生成表单时有与该实例关联的相应数据,原因有两个。 label打印,通过调试,我可以看到实例在newFooForm方法返回视图名称之前具有相应的数据。

每当我提交表单时,除了从表单传递的值外,每个fooField的所有数据都设置为null。我知道这是因为,1。数据没有保留,2。调试显示。这是用于提交提交的控制器方法:

@RequestMapping(method = RequestMethod.POST, params = {"save"})
public String fooFormDraftSubmit(@AuthenticationPrincipal UserDetails user, @ModelAttribute FooViewModel fooViewModel, Model model) {
    Employee currentUser = getCurrentUser(user);
    Foo foo = new Foo(currentUser, fooViewModel);
    fooService.save(foo);
    for (FooField fooField : fooViewModel.getFooFields()) {
       fooFieldService.save(fooField);
    }
    FooViewModel persistedFooViewModel = new FooViewModel(foo);
    model.addAttribute("fooViewModel", persistedFooViewModel);
    return "fooView";
}

感谢您的任何建议!

1 个答案:

答案 0 :(得分:1)

由于这篇文章我想出了这个:Spring MVC 3 Command Object values being lost between GET and POST operation。具体建议是使用隐藏字段。您必须访问在页面上呈现的ViewModel的属性值,并将其分配给您希望传递到ViewModel端点的POST

<form id="foo-form" action="#" th:action="@{/fooForms}" th:object="${fooViewModel}"
      method="post">
    <div th:each="fooField,iterationStatus  : *{fooFields}">
        <label th:text="${fooField.label}">Label</label>
        <input th:type="text" th:field="*{fooFields[__${iterationStatus.index}__].value}"/>
<!-- The fix, this is an example of 1 attribute.  Of course I will extend this for appropriate attribute values -->
        <input th:type="hidden" th:field="*{fooFields[__${iterationStatus.index}__].label}" th:value="${fooViewModel.fooFields[__${iterationStatus.index}__].label}"/>
<!-- End new code -->
    </div>
    <div style="position: absolute; right: 20px; bottom: 20px;">
        <input class="btn btn-primary" id="save" type="submit" name="save" value="Save"/>
        <input class="btn btn-primary" id="submit" type="submit" name="submit" value="Submit"/>
    </div>
</form>