Spring 绑定列表<对象>形成:复选框

发布于 2024-12-05 01:10:45 字数 5985 浏览 0 评论 0原文

我似乎无法将我的表单绑定到复选框控件。我在这里阅读了很多帖子并尝试了一些技术,但没有运气。也许新的眼光会有所帮助。

我的控制器:

public String editAccount(@RequestParam("id") String id, Model model) {
    model.addAttribute("account", accountService.getAccount(id));
    model.addAttribute("allRoles", roleService.getRoles());
    return EDIT_ACCOUNT;
}

我的jsp:

<form:form action="" modelAttribute="account">
<form:checkboxes items="${allRoles}" path="roles" itemLabel="name" itemValue="id" delimiter="<br/>"/>
</form>

生成的html:

<span><input id="roles1" name="roles" type="checkbox" value="1"/><label for="roles1">User</label></span><span><br/><input id="roles2" name="roles" type="checkbox" value="2"/><label for="roles2">Admin</label></span><span><br/><input id="roles3" name="roles" type="checkbox" value="3"/><label for="roles3">SuperAdmin</label></span<input type="hidden" name="_roles" value="on"/>

我为每个循环使用了第二个循环(未显示)以确保模型对象包含角色。确实如此,但没有选中任何复选框,并且当我提交角色对象时始终为空。有人可以告诉我我错过了什么吗?

谢谢

编辑

抱歉刚刚意识到查看帐户和角色对象可能会有所帮助:

public class Account {

    private String username, firstName, lastName, email;
    private List<Role> roles;

    @NotNull
    @Size(min = 1, max = 50)
    public String getUsername() {
        return username;
    }

    public void setUsername(String username) {
        this.username = username;
    }

    @NotNull
    @Size(min = 1, max = 50)
    public String getFirstName() {
        return firstName;
    }

    public void setFirstName(String firstName) {
        this.firstName = firstName;
    }

    @NotNull
    @Size(min = 1, max = 50)
    public String getLastName() {
        return lastName;
    }

    public void setLastName(String lastName) {
        this.lastName = lastName;
    }

    @NotNull
    @Size(min = 6, max = 50)
    public String getEmail() {
        return email;
    }

    public void setEmail(String email) {
        this.email = email;
    }

    public List<Role> getRoles() {
        return roles;
    }

    public void setRoles(List<Role> roles) {
        this.roles = roles;
    }

    public String toString() {
        return ReflectionToStringBuilder.toString(this);
    }

}

public class Role {

private int id;
private String name;

public Role() {}

public Role(int id, String name) {
    this.id = id;
    this.name = name;
}

public int getId() {
    return id;
}

public void setId(int id) {
    this.id = id;
}

@NotNull
@Size(min = 1, max = 50)
public String getName() {
    return name;
}

public void setName(String name) {
    this.name = name;
}

}

编辑#2

控制器发布方法

@RequestMapping(value = "edit", method = RequestMethod.POST)
public String updateAccount(@RequestParam("id") String id, @ModelAttribute("account") @Valid AccountEditForm form, BindingResult result) {
    System.out.println("FORM VALUES AFTER: " + form);
    return (result.hasErrors() ? EDIT_ACCOUNT : ACCOUNT_REDIRECT);
}

AccountEditForm 是表单支持对象。当我执行 GET 操作时,我会抓取一个 Account 对象并将值传递到 AccountEditForm 中,然后再显示屏幕。为了清楚起见,我将附上 AccountEditForm。它与帐户对象非常相似。我只是碰巧将表单对象与模型对象分开。

public class AccountEditForm {

    private String username, firstName, lastName, email;
    private List<Role> roles = new ArrayList<Role>();

    @NotNull
    @Size(min = 1, max = 50)
    public String getUsername() {
        return username;
    }

    public void setUsername(String username) {
        this.username = username;
    }

    @NotNull
    @Size(min = 1, max = 50)
    public String getFirstName() {
        return firstName;
    }

    public void setFirstName(String firstName) {
        this.firstName = firstName;
    }

    @NotNull
    @Size(min = 1, max = 50)
    public String getLastName() {
        return lastName;
    }

    public void setLastName(String lastName) {
        this.lastName = lastName;
    }

    @NotNull
    @Size(min = 6, max = 50)
    public String getEmail() {
        return email;
    }

    public void setEmail(String email) {
        this.email = email;
    }

    public List<Role> getRoles() {
        return roles;
    }

    public void setRoles(List<Role> roles) {
        this.roles = roles;
    }

    public String toString() {
        return ReflectionToStringBuilder.toString(this);
    }

}

编辑#3角色属性编辑器

public class RolePropertyEditor extends PropertyEditorSupport {

    private Map<Integer, Role> roleMap = new HashMap<Integer, Role>();

    public RolePropertyEditor(List<Role> roleList) {
        for (Role r : roleList) roleMap.put(r.getId(), r);
    }

    public void setAsText(String incomingId) {
        Role role = roleMap.get(incomingId);
        System.out.println("PROPERTY EDITOR ROLE " + role);
        setValue(role);
    }

    public String getAsText() {
        System.out.println("PROPERTY EDITOR ID " + ((Role)getValue()).getId());
        return String.valueOf(((Role)getValue()).getId());
    }
}

在我的控制器中定义,例如:

@InitBinder
public void initBinder(WebDataBinder binder) {
    binder.setAllowedFields(new String[] {
            "username", "password", "confirmPassword", "firstName", "lastName", "email", "acceptTerms", "currentPassword"
    });
    binder.registerCustomEditor(Role.class, new RolePropertyEditor(roleService.getRoles()));
}

编辑#4新ProeprtyEditor

public class SecurityRolePropertyEditor extends PropertyEditorSupport {

    private RoleService roleService;

    public SecurityRolePropertyEditor(RoleService roleService) {
        this.roleService = roleService;
    }

    public void setAsText(final String name) {
        Role role = roleService.getRoleByName(name);
        setValue(role);
    }
}

I can't seem to get my form to bind to the checkboxes control. I read many posts on here and tried a few techniques but no luck. Maybe a fresh set of eyes will help.

my controller:

public String editAccount(@RequestParam("id") String id, Model model) {
    model.addAttribute("account", accountService.getAccount(id));
    model.addAttribute("allRoles", roleService.getRoles());
    return EDIT_ACCOUNT;
}

my jsp:

<form:form action="" modelAttribute="account">
<form:checkboxes items="${allRoles}" path="roles" itemLabel="name" itemValue="id" delimiter="<br/>"/>
</form>

the generated html:

<span><input id="roles1" name="roles" type="checkbox" value="1"/><label for="roles1">User</label></span><span><br/><input id="roles2" name="roles" type="checkbox" value="2"/><label for="roles2">Admin</label></span><span><br/><input id="roles3" name="roles" type="checkbox" value="3"/><label for="roles3">SuperAdmin</label></span<input type="hidden" name="_roles" value="on"/>

I used a second for each loop (not shown) to make sure that the model object contained the roles. It does, yet none of the checkboxes are checked and when I submit the roles object is always empty. Can someone please tell me what I'm missing?

Thanks

EDIT

Sorry just realized it might be helpful to see the account and role objects:

public class Account {

    private String username, firstName, lastName, email;
    private List<Role> roles;

    @NotNull
    @Size(min = 1, max = 50)
    public String getUsername() {
        return username;
    }

    public void setUsername(String username) {
        this.username = username;
    }

    @NotNull
    @Size(min = 1, max = 50)
    public String getFirstName() {
        return firstName;
    }

    public void setFirstName(String firstName) {
        this.firstName = firstName;
    }

    @NotNull
    @Size(min = 1, max = 50)
    public String getLastName() {
        return lastName;
    }

    public void setLastName(String lastName) {
        this.lastName = lastName;
    }

    @NotNull
    @Size(min = 6, max = 50)
    public String getEmail() {
        return email;
    }

    public void setEmail(String email) {
        this.email = email;
    }

    public List<Role> getRoles() {
        return roles;
    }

    public void setRoles(List<Role> roles) {
        this.roles = roles;
    }

    public String toString() {
        return ReflectionToStringBuilder.toString(this);
    }

}

public class Role {

private int id;
private String name;

public Role() {}

public Role(int id, String name) {
    this.id = id;
    this.name = name;
}

public int getId() {
    return id;
}

public void setId(int id) {
    this.id = id;
}

@NotNull
@Size(min = 1, max = 50)
public String getName() {
    return name;
}

public void setName(String name) {
    this.name = name;
}

}

EDIT #2

Controller Post Method

@RequestMapping(value = "edit", method = RequestMethod.POST)
public String updateAccount(@RequestParam("id") String id, @ModelAttribute("account") @Valid AccountEditForm form, BindingResult result) {
    System.out.println("FORM VALUES AFTER: " + form);
    return (result.hasErrors() ? EDIT_ACCOUNT : ACCOUNT_REDIRECT);
}

AccountEditForm is the form backing object. When I do a GET I grab an Account object and pass the values into an AccountEditForm before displaying the screen. I will attach the AccountEditForm just for clarity. It is very similiar to the account object. I just happened to seperate my form objects from my model objects.

public class AccountEditForm {

    private String username, firstName, lastName, email;
    private List<Role> roles = new ArrayList<Role>();

    @NotNull
    @Size(min = 1, max = 50)
    public String getUsername() {
        return username;
    }

    public void setUsername(String username) {
        this.username = username;
    }

    @NotNull
    @Size(min = 1, max = 50)
    public String getFirstName() {
        return firstName;
    }

    public void setFirstName(String firstName) {
        this.firstName = firstName;
    }

    @NotNull
    @Size(min = 1, max = 50)
    public String getLastName() {
        return lastName;
    }

    public void setLastName(String lastName) {
        this.lastName = lastName;
    }

    @NotNull
    @Size(min = 6, max = 50)
    public String getEmail() {
        return email;
    }

    public void setEmail(String email) {
        this.email = email;
    }

    public List<Role> getRoles() {
        return roles;
    }

    public void setRoles(List<Role> roles) {
        this.roles = roles;
    }

    public String toString() {
        return ReflectionToStringBuilder.toString(this);
    }

}

EDIT #3 Role Property Editor

public class RolePropertyEditor extends PropertyEditorSupport {

    private Map<Integer, Role> roleMap = new HashMap<Integer, Role>();

    public RolePropertyEditor(List<Role> roleList) {
        for (Role r : roleList) roleMap.put(r.getId(), r);
    }

    public void setAsText(String incomingId) {
        Role role = roleMap.get(incomingId);
        System.out.println("PROPERTY EDITOR ROLE " + role);
        setValue(role);
    }

    public String getAsText() {
        System.out.println("PROPERTY EDITOR ID " + ((Role)getValue()).getId());
        return String.valueOf(((Role)getValue()).getId());
    }
}

Defined in my controller like:

@InitBinder
public void initBinder(WebDataBinder binder) {
    binder.setAllowedFields(new String[] {
            "username", "password", "confirmPassword", "firstName", "lastName", "email", "acceptTerms", "currentPassword"
    });
    binder.registerCustomEditor(Role.class, new RolePropertyEditor(roleService.getRoles()));
}

EDIT #4 NEW ProeprtyEditor

public class SecurityRolePropertyEditor extends PropertyEditorSupport {

    private RoleService roleService;

    public SecurityRolePropertyEditor(RoleService roleService) {
        this.roleService = roleService;
    }

    public void setAsText(final String name) {
        Role role = roleService.getRoleByName(name);
        setValue(role);
    }
}

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

○闲身 2024-12-12 01:10:45

将 equals 方法添加到您的 Roles 实体。

请参阅此答案(Spring MVC 预填充复选框):类似的问题以获取更多详细信息。

Add an equals method to your Roles entity.

see this answer (Spring MVC Pre Populate Checkboxes): of a similar question for more details.

雨后彩虹 2024-12-12 01:10:45

您似乎缺少实体上的实现 equalshashCode 方法。

It seems you are missing implementation equals and hashCode method on your entities.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文