Spring Thymeleaf Form Multi-Checkboxes Mapping with Collection Example
- Details
- Written by Nam Ha Minh
- Last Updated on 30 April 2020   |   Print Email
In this quick post, I will share with you some code examples to display multiple checkboxes in HTML form with Spring MVC and Thymeleaf. The values of the checkboxes are mapped with a collection which is a field of a model class. For example, you want to code the user form that looks like this:
A user can have one or more (multiple) roles, so the Roles field in this form is represented with multiple checkboxes corresponding to role names in the database.
In the database, we have 3 tables to implement many-to-many relationship between users and roles as follows:
In Java code, we create the entity class User as follows (I show only the relevant code in the context of this post):
package net.codejava import java.util.*; import javax.persistence.* @Entity @Table(name = "users") public class User { @ManyToMany(cascade = CascadeType.PERSIST, fetch = FetchType.EAGER) @JoinTable( name = "users_roles", joinColumns = @JoinColumn(name = "user_id"), inverseJoinColumns = @JoinColumn(name = "role_id") ) private Set<Role> roles = new HashSet<>(); }
You see, the User class has a Set of Roles. You should override toString(), equals() and hashCode() in the Role class as follows:
package net.codejava; import javax.persistence.*; @Entity @Table(name = "roles") public class Role { @Id @GeneratedValue(strategy = GenerationType.IDENTITY) private Integer id; private String name; // getters and setters are not shown @Override public String toString() { return this.name; } @Override public int hashCode() { final int prime = 31; int result = 1; result = prime * result + ((id == null) ? 0 : id.hashCode()); return result; } @Override public boolean equals(Object obj) { if (this == obj) return true; if (obj == null) return false; if (getClass() != obj.getClass()) return false; Role other = (Role) obj; if (id == null) { if (other.id != null) return false; } else if (!id.equals(other.id)) return false; return true; } }
We need to override toString() method so role names will be shown in the form. And equals() and hashCode() must be overridden so Spring MVC and Thymeleaf will show the check marks correctly when the form is in edit mode.
For Spring Data JPA repository interfaces, i.e. UserRepository and RoleRepository – nothing special. We don’t have to write any extra code.
And in the Spring MVC controller class, we need to code the handlers for create new user and edit existing user as follows:
package net.codejava; @Controller public class UserController { @Autowired private UserServices service; @Autowired private RoleRepository roleRepository; @GetMapping("/users/new") public ModelAndView newUser() { User user = new User(); ModelAndView mav = new ModelAndView("user_form"); mav.addObject("user", user); List<Role> roles = (List<Role>) roleRepository.findAll(); mav.addObject("allRoles", roles); return mav; } @GetMapping("/users/edit/{id}") public ModelAndView editUser(@PathVariable(name = "id") Integer id) { User user = service.get(id); ModelAndView mav = new ModelAndView("user_form"); mav.addObject("user", user); List<Role> roles = (List<Role>) roleRepository.findAll(); mav.addObject("allRoles", roles); return mav; } }
The key point here is to add a collection of Role objects to the model:
List<Role> roles = (List<Role>) roleRepository.findAll(); mav.addObject("allRoles", roles);
And in the view with Thymeleaf, write code for displaying the checkboxes like this:
<form th:action="@{/users/save}" th:object="${user}" method="post"> <p> <label>Roles: <input type="checkbox" name="roles" th:each="role : ${allRoles}" th:text="${role.name}" th:value="${role.id}" th:field="*{roles}" /> </label> </p> </form>
Then when in create new mode, it will show checkboxes with label corresponding to role names in the database:
We don’t have to write any special code for the save user handler method, as Spring MVC, Thymeleaf and Spring Data JPA do an excellent job to automatically persist the User object and associate Role objects.
In edit mode, it will show the check marks correctly according to the association between user and roles, for example:
That’s some code example of how to use Spring and Thymeleaf to easily display multi-checkboxes on a HTML form mapping with values in database nicely. I hope you found this post helpful.
Other Spring Tutorials:
- Understand the core of Spring framework
- Understand Spring MVC
- Understand Spring AOP
- Spring MVC beginner tutorial with Spring Tool Suite IDE
- Spring MVC Form Handling Tutorial
- Spring MVC Form Validation Tutorial
- 14 Tips for Writing Spring MVC Controller
- Spring Web MVC Security Basic Example (XML Configuration)
- Understand Spring Data JPA with Simple Example
Comments
Great example which works fine with ManyToMany
What about OneToMany/ManyToOne Please ?
I tried to change checkbox to input text and it does not work for onetomany/manytoone....
You could make your tutorial complete by including that part.
Otherwise a nice tutorial!
Do not use DTO in this case. DTO should be use for transferring data from RESTful webservices to client (browser).