Spring 绑定列表<对象>形成:复选框对象>
我似乎无法将我的表单绑定到复选框控件。我在这里阅读了很多帖子并尝试了一些技术,但没有运气。也许新的眼光会有所帮助。
我的控制器:
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 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
将 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.
您似乎缺少实体上的实现
equals
和hashCode
方法。It seems you are missing implementation
equals
andhashCode
method on your entities.