Spring MVC Tutorial

Core Spring MVC

Spring MVC - Annotation

Spring MVC - Form Handling

Spring MVC with JSTL

Spring MVC with REST API

Spring MVC with Database

Two-Way Data Binding in Spring MVC with Example

In traditional web development, two-way data binding is a feature primarily associated with frontend frameworks like Angular, React (with additional libraries), or Vue.js. These frameworks allow automatic synchronization of data between the model (typically JavaScript variables) and the view (UI elements).

However, in the context of Spring MVC, the concept of two-way data binding typically refers to the ability to:

  • Populate form fields in the view (JSP, Thymeleaf, etc.) with values from the model.
  • Automatically collect and bind form data to the model when the form is submitted.

Spring MVC provides this via the @ModelAttribute annotation.

Example:

Let's see a simple example using Spring MVC where a user can edit their profile:

  • Model (POJO)
public class UserProfile {
    private String name;
    private String email;

    // Constructors, getters, and setters...
}
  • Controller
@Controller
@RequestMapping("/profile")
public class UserProfileController {

    // Simulate a user profile from the database
    UserProfile userProfile = new UserProfile("John Doe", "john.doe@example.com");

    @GetMapping("/edit")
    public String showEditProfile(Model model) {
        model.addAttribute("userProfile", userProfile);
        return "editProfile";
    }

    @PostMapping("/save")
    public String saveProfile(@ModelAttribute UserProfile userProfile) {
        this.userProfile = userProfile;  // Typically, you'd save this to the database
        return "redirect:/profile/edit"; // Redirect back to the edit page
    }
}
  • View (JSP - editProfile.jsp)
<%@ taglib prefix="form" uri="http://www.springframework.org/tags/form" %>
<html>
<head>
    <title>Edit Profile</title>
</head>
<body>
    <form:form action="/profile/save" method="post" modelAttribute="userProfile">
        <div>
            <form:label path="name">Name</form:label>
            <form:input path="name" />
        </div>
        <div>
            <form:label path="email">Email</form:label>
            <form:input path="email" />
        </div>
        <div>
            <input type="submit" value="Save" />
        </div>
    </form:form>
</body>
</html>

Explanation:

  • When a user navigates to /profile/edit, the showEditProfile method is invoked. This method populates the model with the current user profile, which is then used to fill the form fields (name and email).

  • After editing the form, the user can submit it. The form data is then automatically collected and bound to the UserProfile object in the saveProfile method (thanks to @ModelAttribute). From here, you can save it to a database, for example.

This example demonstrates two-way data binding in Spring MVC:

  • Model to View: The form fields are populated with data from the model.
  • View to Model: Upon form submission, form data is automatically collected and bound to the model.

Remember to add the necessary dependencies and configuration for Spring MVC to make the above example work.

  1. Using ModelAttribute for two-way data binding in Spring:

    @Controller
    @RequestMapping("/example")
    public class ExampleController {
    
        @GetMapping("/showForm")
        public String showForm(Model model) {
            model.addAttribute("user", new User());
            return "user-form";
        }
    
        @PostMapping("/processForm")
        public String processForm(@ModelAttribute("user") User user) {
            // The "user" object now contains the form data
            return "confirmation";
        }
    }
    

    Here, User is a form backing object with fields corresponding to the form inputs.

  2. Spring MVC form data binding example:

    @Controller
    @RequestMapping("/employee")
    public class EmployeeController {
    
        @GetMapping("/showForm")
        public String showForm(Model model) {
            model.addAttribute("employee", new Employee());
            return "employee-form";
        }
    
        @PostMapping("/processForm")
        public String processForm(@ModelAttribute("employee") Employee employee) {
            // Process the form data
            return "confirmation";
        }
    }
    

    The Employee class is a form backing object with fields corresponding to the form inputs.

  3. Two-way data binding with Thymeleaf in Spring MVC:

    <!-- Thymeleaf template: employee-form.html -->
    <form th:action="@{/employee/processForm}" th:object="${employee}" method="post">
        <input type="text" th:field="*{firstName}" />
        <input type="text" th:field="*{lastName}" />
        <button type="submit">Submit</button>
    </form>
    

    Thymeleaf's th:field attribute enables two-way data binding.

  4. Custom converters for two-way data binding in Spring:

    public class StringToUserConverter implements Converter<String, User> {
    
        @Override
        public User convert(String source) {
            // Convert string to User object
        }
    }
    

    Register the converter in a configuration class:

    @Configuration
    public class WebConfig implements WebMvcConfigurer {
    
        @Override
        public void addFormatters(FormatterRegistry registry) {
            registry.addConverter(new StringToUserConverter());
        }
    }
    
  5. Handling form submissions with two-way data binding in Spring:

    @Controller
    @RequestMapping("/example")
    public class ExampleController {
    
        @PostMapping("/processForm")
        public String processForm(@ModelAttribute("user") User user) {
            // Process form data
            return "confirmation";
        }
    }
    

    Here, User is the form backing object with fields corresponding to the form inputs.

  6. Spring MVC model attribute and form binding:

    @Controller
    @RequestMapping("/example")
    public class ExampleController {
    
        @ModelAttribute("user")
        public User getUser() {
            return new User();
        }
    
        @GetMapping("/showForm")
        public String showForm() {
            return "user-form";
        }
    
        @PostMapping("/processForm")
        public String processForm(@ModelAttribute("user") User user) {
            // Process form data
            return "confirmation";
        }
    }
    

    The @ModelAttribute annotated method provides the form backing object to the model.

  7. Binding form data to model in Spring MVC:

    @Controller
    @RequestMapping("/example")
    public class ExampleController {
    
        @GetMapping("/showForm")
        public String showForm(Model model) {
            model.addAttribute("user", new User());
            return "user-form";
        }
    
        @PostMapping("/processForm")
        public String processForm(User user, Model model) {
            // Process form data
            model.addAttribute("user", user);
            return "confirmation";
        }
    }
    

    Here, the User object is automatically populated with form data.