从Spring的AutoPopulatingList中删除项目

时间:2012-06-12 09:38:38

标签: jquery spring spring-mvc

我使用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 个答案:

答案 0 :(得分: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));

希望这会对你有所帮助。欢呼声。

答案 1 :(得分: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”)解决了这个问题。 现在从表单中删除的对象确实是null。

现在我正在努力将它们从列表中删除,然后才能继续,因为

removeAll(Collections.singleton(null));

似乎不起作用。

答案 2 :(得分:0)

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

为了清楚起见,jsp + spring将如何将数据绑定到list元素。对于绑定列表的第i个元素,它将调用list.get(i).set(newVal)。所以当你从视图中删除第i个元素时,没有任何东西会被绑定,但同时我的元素也不会被删除。

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

答案 3 :(得分:0)

用户“Japs T”提出的Soluton对我来说也不起作用:

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

我对可能的解决方案很感兴趣。这是清单:

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

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

interface Removeable {
boolean isEmpty();
}

(Collection<Removeable>)myCollection.removeIf(e -> e.isEmpty())