0

我使用 Spring AutoPopulatingList 和 JQuery 创建了一个动态表单。加法就像一个魅力,新项目被创建并持久化到数据库中。问题在于删除:我的更新方法总是得到完整的列表,不管浏览器端的元素是否被删除。

Controller的更新方法就这么简单

@RequestMapping(value = "/user/{id}", method = RequestMethod.POST)
@ResponseBody
public String updateUser(@PathVariable("id") int id, @ModelAttribute("user") User user, HttpServletRequest request) {
    userService.update(user);
    return messageSource.getMessage("user.data_updated", null, request.getLocale());
}

用户POJO实现如下

@Entity
public class User implements Serializable {
...

@OneToMany(targetEntity = Language.class, fetch = FetchType.EAGER, cascade = CascadeType.ALL)
private List<Language> languages = new AutoPopulatingList(Language.class);
...
}

发送到我的控制器的 POST 请求如下所示(另外,添加了语言 2):

languages[0].code:pl
languages[0].level:Fluent
languages[1].code:de
languages[1].level:Native
languages[2].code:cc
languages[2].level:Intermediate

和移除(使用 JQuery .remove()方法移除语言 1):

languages[0].code:pl
languages[0].level:Fluent
languages[2].code:cc
languages[2].level:Intermediate

所以从通信方面看起来不错,但是在 updateUser 方法中从 @ModelAttribute("user") 检索到的用户仍然具有三个语言元素,都是有效的(即不为空)。有什么建议么?如果相关,我正在使用 Spring 3.1.1 和 JQuery 1.7.2。

编辑:添加/删除字段的客户端代码如下:

$.addLanguage = function()  {
            var newLanguage = $('<input type="text" id="languages' + languagesCounter + '.code" name="languages[' + languagesCounter + '].code" class="langIdentifier"/>' +
                                '<select id="languages' + languagesCounter + '.level" name="languages[' + languagesCounter + '].level" class="langSelect">'  +
                                    '<option value="Basic">Basic</option>' +
                                    '<option value="Intermediate">Intermediate</option>' +
                                    '<option value="Fluent">Fluent</option>' +
                                    '<option value="Native">Native</option>' +
                                '</select>' +
                                '<input type="button" id="remove' + languagesCounter + '" onclick="$.removeLanguage(' + languagesCounter + ')"' +
                                        'name="Remove" value="Remove" class="removeButton"/>' +
                                '<br/>');
            languagesCounter++;
            newLanguage.insertBefore($("#add"));
        }

并删除:

$.removeLanguage = function(languageId) {
    var languageField = '#languages' + languageId + '\\.code';
    var levelField = '#languages' + languageId + '\\.level';
    var removeButton = '#remove' + languageId;
    $(languageField).fadeOut(250, function() { $(this).remove(); });
    $(levelField).fadeOut(250, function() { $(this).remove(); });
    $(removeButton).fadeOut(250, function() { $(this).remove(); });
};
4

4 回答 4

0

尝试使用LazyList而不是AutoPopulatingList。我正在使用它将动态内容添加到 html 并将数据返回到模型属性对象中。下面是我用来创建列表的代码。

    private List<OperationParameters> operationParameterses = LazyList.decorate(new ArrayList<OperationParameters>(), FactoryUtils.instantiateFactory(OperationParameters.class));

    @OneToMany(cascade=CascadeType.ALL, fetch=FetchType.LAZY, mappedBy="operations")
    public List<OperationParameters> getOperationParameterses() {
        return this.operationParameterses;
    }

    public void setOperationParameterses(List<OperationParameters> operationParameterses) {
        this.operationParameterses = operationParameterses;
    }

在控制器中,当我在模型属性中填充列表时,我首先检查列表中的空数据并使用以下代码将其删除,然后持久保存在数据库中。否则它会尝试在数据库中插入空数据。

operations.getOperationParameterses().removeAll(Collections.singleton(null));

希望这对您有所帮助。干杯。

于 2012-06-12T09:54:31.613 回答
0

当您使用 jquery 从视图中删除列表元素标记时,它只会阻止 spring 将新值绑定到该元素。但它不会从控制器的列表中删除元素。

为了清楚起见,这里是 jsp + spring 如何将数据绑定到列表元素。为了绑定列表的第 i 个元素,它将调用 list.get(i).set(newVal)。因此,当您从视图中删除第 i 个元素时,不会绑定任何内容,但同时第 i 个元素也不会被删除。

对于删除,您可能会在每次删除元素并从控制器中的列表中删除元素时发送 ajax 请求。

于 2014-07-08T19:30:06.277 回答
0

回答我自己的问题(也许会让人头疼):

我有过

@ModelAttribute("user")
public User getUserById(@PathVariable("id") int id) {
    logger.fine("Getting user for id: " + id);
    return userService.findById(id);
}

在 GET 中填充模型,以及

@RequestMapping(value = "/user/{id}", method = RequestMethod.POST)
@ResponseBody
public String updateUser(@PathVariable("id") int id, @ModelAttribute("user") User user, HttpServletRequest request) {
    userService.update(user);
    return messageSource.getMessage("user.data_updated", null, request.getLocale());
}

更新用户。现在整个问题出在 POST 处理程序中的 @ModelAttribute 中——它不能与预填充代码中的键名相同。将其更改为 @ModelAttribute("updated") 解决了这个问题。现在从表单中删除的对象确实是空的。

现在我正在努力在坚持之前将它们从列表中删除,因为

removeAll(Collections.singleton(null));

似乎不起作用。

于 2012-06-24T17:01:01.177 回答
0

用户“Japs T”提出的解决方案对我也不起作用:

operations.getOperationParameterses().removeAll(Collections.singleton(null));

我对可能的解决方案感到满意。这是列表:

  • 在从请求中绑定值之前删除服务器端的所有项目
  • 通过 AJAX 更新服务器状态

我会尝试的“不透明”解决方案是隐藏 HTML 元素而不是删除和清除输入中的值,然后在服务器端您可以实现忽略“空”记录的功能。例如:

interface Removeable {
boolean isEmpty();
}

(Collection<Removeable>)myCollection.removeIf(e -> e.isEmpty())
于 2016-01-15T18:20:55.570 回答