Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Spring Binding List<Object> to Form:checkboxes

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);
    }
}
like image 558
blong824 Avatar asked Sep 14 '11 18:09

blong824


1 Answers

Add an equals method to your Roles entity.

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

like image 156
Ralph Avatar answered Nov 14 '22 01:11

Ralph