|  | 
|  | 1 | +# 9.4 - Form Data Binding - Text Box | 
|  | 2 | + | 
|  | 3 | +## Introduction | 
|  | 4 | + | 
|  | 5 | +Welcome to **9.4 - Form Data Binding - Text Box** | 
|  | 6 | + | 
|  | 7 | +In this section, we’re building on [9.3](#93-reading-form-data) by making form handling in Spring MVC even smarter. Instead of grabbing form data with `@RequestParam`, we’ll bind it directly to a Java object (a "bean") using Spring’s form data binding magic. We’ll create a form to collect a student’s first and last name, send it to the server, and display a confirmation page—all tied to a `Student` class. This is a game-changer for beginners wanting to simplify user input in web apps! 📋 | 
|  | 8 | + | 
|  | 9 | +--- | 
|  | 10 | + | 
|  | 11 | +## Table of Contents | 
|  | 12 | + | 
|  | 13 | +1. [What Is Form Data Binding in Spring MVC?](#1-what-is-form-data-binding-in-spring-mvc) | 
|  | 14 | + - [1.1 Overview](#11-overview) | 
|  | 15 | + - [1.2 Application Flow](#12-application-flow) | 
|  | 16 | + - [1.3 Key Concepts](#13-key-concepts) | 
|  | 17 | + - [1.4 Key Terms for Beginners](#14-key-terms-for-beginners) | 
|  | 18 | +2. [Learning Roadmap](#2-learning-roadmap) | 
|  | 19 | + - [2.1 Creating the Student Bean](#21-creating-the-student-bean) | 
|  | 20 | + - [2.2 Setting Up the Controller](#22-setting-up-the-controller) | 
|  | 21 | + - [2.3 Building the Form View](#23-building-the-form-view) | 
|  | 22 | + - [2.4 Processing and Confirming the Form](#24-processing-and-confirming-the-form) | 
|  | 23 | +3. [Practical Demonstration](#3-practical-demonstration) | 
|  | 24 | + - [3.1 Creating the Project](#31-creating-the-project) | 
|  | 25 | + - [3.2 Writing the Student Class](#32-writing-the-student-class) | 
|  | 26 | + - [3.3 Writing the Controller](#33-writing-the-controller) | 
|  | 27 | + - [3.4 Building the Form Page](#34-building-the-form-page) | 
|  | 28 | + - [3.5 Building the Confirmation Page](#35-building-the-confirmation-page) | 
|  | 29 | + - [3.6 Running and Testing](#36-running-and-testing) | 
|  | 30 | +4. [What’s Next](#4-whats-next) | 
|  | 31 | + | 
|  | 32 | +--- | 
|  | 33 | + | 
|  | 34 | +## 1. What Is Form Data Binding in Spring MVC? | 
|  | 35 | + | 
|  | 36 | +### 1.1 Overview | 
|  | 37 | + | 
|  | 38 | +- **Goal**: Automatically connect form inputs (like text fields) to a Java object, then use that object to show results. | 
|  | 39 | +- **What You’ll Build**: A web app where: | 
|  | 40 | + 1. A form asks for a student’s first name and last name. | 
|  | 41 | + 2. You type something (e.g., "James" and "Gosling"). | 
|  | 42 | + 3. The server binds it to a `Student` object and shows "Student is confirmed: James Gosling". | 
|  | 43 | +- **Why It’s Awesome**: No more manually grabbing each field with `@RequestParam`—Spring does the heavy lifting! | 
|  | 44 | +- **Tools**: | 
|  | 45 | + - **Spring MVC**: Manages the app’s flow. | 
|  | 46 | + - **Thymeleaf**: Displays dynamic forms and results. | 
|  | 47 | + - **Java Bean**: A simple class (e.g., `Student`) to hold data. | 
|  | 48 | + | 
|  | 49 | +#### Real-World Analogy | 
|  | 50 | + | 
|  | 51 | +Think of form data binding as a librarian (Spring) who takes your book request form (first name, last name), fills out a catalog card (Java object), and hands it to the display desk (view) to show you—all without you touching the card yourself! | 
|  | 52 | + | 
|  | 53 | +### 1.2 Application Flow | 
|  | 54 | + | 
|  | 55 | +- **Steps Explained**: | 
|  | 56 | + 1. **Show Form**: Visit `http://localhost:8080/showStudentForm`. The server sends `student-form.html` with fields for first and last name, tied to a `Student` object. | 
|  | 57 | + 2. **Submit Form**: Type "James" and "Gosling", hit submit. Data goes to `POST /processStudentForm`. | 
|  | 58 | + 3. **Process Data**: Spring binds "James" and "Gosling" to a `Student` object’s fields, logs it, and prepares `student-confirmation.html`. | 
|  | 59 | + 4. **Show Confirmation**: See "Student is confirmed: James Gosling" on the page and in the console. | 
|  | 60 | +- **Diagram**: | 
|  | 61 | + - Browser → `GET /showStudentForm` → Controller → `student-form.html` → Submit → `POST /processStudentForm` → Controller → `student-confirmation.html` → Browser. | 
|  | 62 | + | 
|  | 63 | +### 1.3 Key Concepts | 
|  | 64 | + | 
|  | 65 | +- **Form Data Binding**: Links form fields (e.g., `<input name="firstName">`) to a Java object’s properties (e.g., `student.setFirstName()`). | 
|  | 66 | +- **Java Bean**: A simple class with private fields (e.g., `firstName`), getters, and setters—Spring uses these to store and retrieve data. | 
|  | 67 | +- **Model Attribute**: The `Student` object is shared between controller and view via the `Model`—like a shared notebook. | 
|  | 68 | +- **Getters and Setters**: | 
|  | 69 | + - **Load Form**: Spring calls `getFirstName()` to fill the form (if data exists). | 
|  | 70 | + - **Submit Form**: Spring calls `setFirstName()` to save what you typed. | 
|  | 71 | +- **Comparison to Past Lessons**: | 
|  | 72 | + - **Jackson Binding**: JSON → Java object (REST APIs). | 
|  | 73 | + - **ORM Binding**: Java object → Database (JPA). | 
|  | 74 | + - **Form Binding**: HTML form → Java object (this lesson!). | 
|  | 75 | + | 
|  | 76 | +>[!NOTE] | 
|  | 77 | +>Binding skips manual data grabbing—Spring matches field names automatically! | 
|  | 78 | +
 | 
|  | 79 | +### 1.4 Key Terms for Beginners | 
|  | 80 | + | 
|  | 81 | +Your newbie dictionary—learn these and you’re golden! | 
|  | 82 | + | 
|  | 83 | +| Term | Meaning | Example | Why It’s Cool | | 
|  | 84 | +|-----------------------|----------------------------------------------|-------------------------------|-----------------------| | 
|  | 85 | +| **Form Data Binding** | Auto-links form inputs to a Java object | Form → `Student` | Less code, more magic! | | 
|  | 86 | +| **Java Bean** | A class with fields, getters, and setters | `Student` with `firstName` | Holds data neatly | | 
|  | 87 | +| **`@ModelAttribute`** | Grabs a bound object in the controller | `@ModelAttribute("student")` | Easy data access | | 
|  | 88 | +| **`th:object`** | Ties a form to a Java object in Thymeleaf | `th:object="${student}"` | Binding starts here | | 
|  | 89 | +| **`th:field`** | Links a form field to an object property | `th:field="*{firstName}"` | Auto-maps fields | | 
|  | 90 | +| **Model** | A carrier for data between code and view | `model.addAttribute()` | Shares data smoothly | | 
|  | 91 | +| **Getter/Setter** | Methods to read/write object fields | `getFirstName()`, `setLastName()` | Spring’s helpers | | 
|  | 92 | + | 
|  | 93 | +--- | 
|  | 94 | + | 
|  | 95 | +## 2. Learning Roadmap | 
|  | 96 | + | 
|  | 97 | +Your step-by-step path to mastering form data binding! | 
|  | 98 | + | 
|  | 99 | +### 2.1 Creating the Student Bean | 
|  | 100 | + | 
|  | 101 | +- **What**: Build a `Student` class with fields for first and last name. | 
|  | 102 | +- **Goal**: Give Spring a container to bind form data to. | 
|  | 103 | +- **How**: Use private fields and Lombok to auto-generate getters/setters. | 
|  | 104 | + | 
|  | 105 | +### 2.2 Setting Up the Controller | 
|  | 106 | + | 
|  | 107 | +- **What**: Write a controller with two methods—show the form and process it. | 
|  | 108 | +- **Goal**: Manage the app’s flow and bind the `Student` object. | 
|  | 109 | +- **How**: Add the `Student` to the model and use `@ModelAttribute`. | 
|  | 110 | + | 
|  | 111 | +### 2.3 Building the Form View | 
|  | 112 | + | 
|  | 113 | +- **What**: Create a Thymeleaf page with text fields tied to `Student`. | 
|  | 114 | +- **Goal**: Collect user input with binding built-in. | 
|  | 115 | +- **How**: Use `th:object` and `th:field` in the form. | 
|  | 116 | + | 
|  | 117 | +### 2.4 Processing and Confirming the Form | 
|  | 118 | + | 
|  | 119 | +- **What**: Process the submitted `Student` object and show a result. | 
|  | 120 | +- **Goal**: Display and log the bound data. | 
|  | 121 | +- **How**: Read with `@ModelAttribute` and return a confirmation view. | 
|  | 122 | + | 
|  | 123 | +--- | 
|  | 124 | + | 
|  | 125 | +## 3. Practical Demonstration | 
|  | 126 | + | 
|  | 127 | +Let’s build `form-data-binding` to bind and display student names! | 
|  | 128 | + | 
|  | 129 | +### 3.1 Creating the Project | 
|  | 130 | + | 
|  | 131 | +- **Purpose**: Set up a Spring Boot project with Thymeleaf and Lombok. | 
|  | 132 | +- **Tool**: Eclipse (or Spring Initializr at `start.spring.io`). | 
|  | 133 | +- **Steps**: | 
|  | 134 | + 1. **New Project**: File → New → Spring Starter Project. | 
|  | 135 | + 2. **Details**: | 
|  | 136 | + - **Name**: `form-data-binding`. | 
|  | 137 | + - **Type**: Maven (manages libraries). | 
|  | 138 | + - **Java Version**: 17 (modern Java). | 
|  | 139 | + - **Packaging**: JAR (runnable file). | 
|  | 140 | + - **Group**: `com.example`. | 
|  | 141 | + - **Artifact**: `binding`. | 
|  | 142 | + - **Package**: `com.example.binding`. | 
|  | 143 | + 3. **Dependencies**: | 
|  | 144 | + - `Spring Web`: For MVC and Tomcat. | 
|  | 145 | + - `Spring Boot DevTools`: Auto-reloads changes. | 
|  | 146 | + - `Spring Boot Starter Thymeleaf`: For dynamic pages. | 
|  | 147 | + - `Lombok`: Auto-generates boilerplate code (getters, setters). | 
|  | 148 | + 4. **Finish**: Generate and open in Eclipse. | 
|  | 149 | +- **Result**: | 
|  | 150 | + - `pom.xml`: | 
|  | 151 | + ```xml | 
|  | 152 | + <dependencies> | 
|  | 153 | + <dependency> | 
|  | 154 | + <groupId>org.springframework.boot</groupId> | 
|  | 155 | + <artifactId>spring-boot-starter-web</artifactId> | 
|  | 156 | + </dependency> | 
|  | 157 | + <dependency> | 
|  | 158 | + <groupId>org.springframework.boot</groupId> | 
|  | 159 | + <artifactId>spring-boot-starter-thymeleaf</artifactId> | 
|  | 160 | + </dependency> | 
|  | 161 | + <dependency> | 
|  | 162 | + <groupId>org.springframework.boot</groupId> | 
|  | 163 | + <artifactId>spring-boot-devtools</artifactId> | 
|  | 164 | + <scope>runtime</scope> | 
|  | 165 | + <optional>true</optional> | 
|  | 166 | + </dependency> | 
|  | 167 | + <dependency> | 
|  | 168 | + <groupId>org.projectlombok</groupId> | 
|  | 169 | + <artifactId>lombok</artifactId> | 
|  | 170 | + <optional>true</optional> | 
|  | 171 | + </dependency> | 
|  | 172 | + <dependency> | 
|  | 173 | + <groupId>org.springframework.boot</groupId> | 
|  | 174 | + <artifactId>spring-boot-starter-test</artifactId> | 
|  | 175 | + <scope>test</scope> | 
|  | 176 | + </dependency> | 
|  | 177 | + </dependencies> | 
|  | 178 | + ``` | 
|  | 179 | + - Main class: `com.example.binding.FormDataBindingApplication.java`. | 
|  | 180 | + | 
|  | 181 | +>[!TIP] | 
|  | 182 | +>`Lombok` saves you from writing `getFirstName()` by hand—less typing, more fun! | 
|  | 183 | + | 
|  | 184 | +### 3.2 Writing the Student Class | 
|  | 185 | + | 
|  | 186 | +- **Purpose**: Create a bean to hold form data. | 
|  | 187 | +- **File**: `com.example.binding.model.Student.java`. | 
|  | 188 | +- **Code**: | 
|  | 189 | + ```java | 
|  | 190 | + package com.example.binding.model; | 
|  | 191 | + | 
|  | 192 | + import lombok.Data; | 
|  | 193 | + | 
|  | 194 | + @Data | 
|  | 195 | + public class Student { | 
|  | 196 | + private String firstName; | 
|  | 197 | + private String lastName; | 
|  | 198 | + } | 
|  | 199 | + ``` | 
|  | 200 | +- **Line-by-Line Breakdown**: | 
|  | 201 | + - **`package`**: Lives in `model`—keeps beans organized. | 
|  | 202 | + - **`import lombok.Data`**: Brings in Lombok’s superpower. | 
|  | 203 | + - **`@Data`**: Auto-adds getters (`getFirstName()`), setters (`setLastName()`), and more. | 
|  | 204 | + - **`private String firstName`**: Field for the first name. | 
|  | 205 | + - **`private String lastName`**: Field for the last name. | 
|  | 206 | +- **Why Lombok?**: Without it, you’d write 10+ lines for getters, setters, and constructors—`@Data` does it all! | 
|  | 207 | + | 
|  | 208 | +>[!NOTE] | 
|  | 209 | +>Field names (`firstName`, `lastName`) must match form fields—Spring links them by name! | 
|  | 210 | +
 | 
|  | 211 | +### 3.3 Writing the Controller | 
|  | 212 | + | 
|  | 213 | +- **Purpose**: Manage form display and processing with binding. | 
|  | 214 | +- **File**: `com.example.binding.controller.StudentController.java`. | 
|  | 215 | +- **Code**: | 
|  | 216 | + ```java | 
|  | 217 | + package com.example.binding.controller; | 
|  | 218 | + | 
|  | 219 | + import org.slf4j.Logger; | 
|  | 220 | + import org.slf4j.LoggerFactory; | 
|  | 221 | + import org.springframework.stereotype.Controller; | 
|  | 222 | + import org.springframework.ui.Model; | 
|  | 223 | + import org.springframework.web.bind.annotation.GetMapping; | 
|  | 224 | + import org.springframework.web.bind.annotation.ModelAttribute; | 
|  | 225 | + import org.springframework.web.bind.annotation.PostMapping; | 
|  | 226 | + import com.example.binding.model.Student; | 
|  | 227 | + | 
|  | 228 | + @Controller | 
|  | 229 | + public class StudentController { | 
|  | 230 | + | 
|  | 231 | + private static final Logger logger = LoggerFactory.getLogger(StudentController.class); | 
|  | 232 | + | 
|  | 233 | + @GetMapping("/showStudentForm") | 
|  | 234 | + public String showForm(Model model) { | 
|  | 235 | + model.addAttribute("student", new Student()); | 
|  | 236 | + return "student-form"; | 
|  | 237 | + } | 
|  | 238 | + | 
|  | 239 | + @PostMapping("/processStudentForm") | 
|  | 240 | + public String processForm(@ModelAttribute("student") Student student) { | 
|  | 241 | + logger.info("Student: {} {}", student.getFirstName(), student.getLastName()); | 
|  | 242 | + return "student-confirmation"; | 
|  | 243 | + } | 
|  | 244 | + } | 
|  | 245 | + ``` | 
|  | 246 | +- **Line-by-Line Breakdown**: | 
|  | 247 | + - **`import`**: Tools for logging (`Logger`), MVC (`@Controller`), and our `Student` class. | 
|  | 248 | + - **`@Controller`**: Marks this as the app’s request handler. | 
|  | 249 | + - **`Logger`**: For printing to the console—`logger.info` shows messages. | 
|  | 250 | + - **`@GetMapping("/showStudentForm")`**: Runs when you visit `/showStudentForm`. | 
|  | 251 | + - **`Model model`**: Spring’s data carrier—our "notebook". | 
|  | 252 | + - **`new Student()`**: Creates an empty `Student` object (fields blank). | 
|  | 253 | + - **`model.addAttribute("student", ...)`**: Puts the `Student` in the notebook, labeled "student". | 
|  | 254 | + - **`return "student-form"`**: Shows `student-form.html`. | 
|  | 255 | + - **`@PostMapping("/processStudentForm")`**: Runs when the form submits to `/processStudentForm`. | 
|  | 256 | + - **`@ModelAttribute("student") Student student`**: Grabs the bound `Student` object filled with form data. | 
|  | 257 | + - **`logger.info`**: Logs "Student: James Gosling" to the console. | 
|  | 258 | + - **`return "student-confirmation"`**: Shows `student-confirmation.html`. | 
|  | 259 | +- **Key Difference from 9.3**: No `@RequestParam`—binding does it all! | 
|  | 260 | + | 
|  | 261 | +>[!TIP] | 
|  | 262 | +>`"student"` in `addAttribute` and `@ModelAttribute` must match—ties the form to the object! | 
|  | 263 | +
 | 
|  | 264 | +### 3.4 Building the Form Page | 
|  | 265 | + | 
|  | 266 | +- **Purpose**: Make a Thymeleaf form tied to `Student`. | 
|  | 267 | +- **File**: `src/main/resources/templates/student-form.html`. | 
|  | 268 | +- **Code**: | 
|  | 269 | + ```html | 
|  | 270 | + <!DOCTYPE html> | 
|  | 271 | + <html xmlns:th="http://www.thymeleaf.org"> | 
|  | 272 | + <head> | 
|  | 273 | + <title>Student Form</title> | 
|  | 274 | + <link rel="stylesheet" th:href="@{https://cdn.jsdelivr.net/npm/bootstrap@5.3.0/dist/css/bootstrap.min.css}" /> | 
|  | 275 | + </head> | 
|  | 276 | + <body> | 
|  | 277 | + <h2>Student Form</h2> | 
|  | 278 | + <form th:action="@{/processStudentForm}" th:object="${student}" method="post"> | 
|  | 279 | + <label>First Name: </label> | 
|  | 280 | + <input type="text" th:field="*{firstName}" /><br/> | 
|  | 281 | + <label>Last Name: </label> | 
|  | 282 | + <input type="text" th:field="*{lastName}" /><br/> | 
|  | 283 | + <input type="submit" value="Submit" /> | 
|  | 284 | + </form> | 
|  | 285 | + </body> | 
|  | 286 | + </html> | 
|  | 287 | + ``` | 
|  | 288 | +- **Line-by-Line Breakdown**: | 
|  | 289 | + - **`xmlns:th`**: Activates Thymeleaf—links to `http://www.thymeleaf.org`. | 
|  | 290 | + - **`<title>`**: Tab says "Student Form". | 
|  | 291 | + - **`<link>`**: Bootstrap CDN for styling—makes it look nice. | 
|  | 292 | + - **`<h2>`**: Static heading—tells users what’s up. | 
|  | 293 | + - **`<form>`**: Where the action happens. | 
|  | 294 | + - **`th:action="@{/processStudentForm}"`**: Sends data to `/processStudentForm` when submitted. | 
|  | 295 | + - **`th:object="${student}"`**: Ties this form to the "student" object from the model. | 
|  | 296 | + - **`method="post"`**: Hides data in the request body—secure! | 
|  | 297 | + - **`<input th:field="*{firstName}" />`**: Text box bound to `student.firstName`—`*` means "from `th:object`". | 
|  | 298 | + - **`<input th:field="*{lastName}" />`**: Text box bound to `student.lastName`. | 
|  | 299 | + - **`<input type="submit">`**: Button to send the form. | 
|  | 300 | +- **How Binding Works**: | 
|  | 301 | + - **Load**: Spring calls `getFirstName()` (empty here—new object). | 
|  | 302 | + - **Submit**: Spring calls `setFirstName("James")` with what you typed. | 
|  | 303 | + | 
|  | 304 | +>[!NOTE] | 
|  | 305 | +>`*{firstName}` is shorthand for `${student.firstName}`—`*` saves typing! | 
|  | 306 | +
 | 
|  | 307 | +### 3.5 Building the Confirmation Page | 
|  | 308 | + | 
|  | 309 | +- **Purpose**: Show the bound `Student` data. | 
|  | 310 | +- **File**: `src/main/resources/templates/student-confirmation.html`. | 
|  | 311 | +- **Code**: | 
|  | 312 | + ```html | 
|  | 313 | + <!DOCTYPE html> | 
|  | 314 | + <html xmlns:th="http://www.thymeleaf.org"> | 
|  | 315 | + <head> | 
|  | 316 | + <title>Student Confirmation</title> | 
|  | 317 | + <link rel="stylesheet" th:href="@{https://cdn.jsdelivr.net/npm/bootstrap@5.3.0/dist/css/bootstrap.min.css}" /> | 
|  | 318 | + </head> | 
|  | 319 | + <body> | 
|  | 320 | + <h2>Student is confirmed</h2> | 
|  | 321 | + <p>First Name: <span th:text="${student.firstName}"></span></p> | 
|  | 322 | + <p>Last Name: <span th:text="${student.lastName}"></span></p> | 
|  | 323 | + </body> | 
|  | 324 | + </html> | 
|  | 325 | + ``` | 
|  | 326 | +- **Line-by-Line Breakdown**: | 
|  | 327 | + - **`xmlns:th`**: Thymeleaf power—same as before. | 
|  | 328 | + - **`<title>`**: Tab says "Student Confirmation". | 
|  | 329 | + - **`<link>`**: Bootstrap for consistent styling. | 
|  | 330 | + - **`<h2>`**: Static "Student is confirmed" message. | 
|  | 331 | + - **`<p>`**: Shows "First Name: James" using `th:text="${student.firstName}"`—pulls from the model. | 
|  | 332 | + - **`<p>`**: Shows "Last Name: Gosling" with `th:text="${student.lastName}"`. | 
|  | 333 | +- **How It Gets Data**: The `Student` object from `processForm` is still in the model—Thymeleaf reads it. | 
|  | 334 | + | 
|  | 335 | +>[!TIP] | 
|  | 336 | +>Misspell `firstName`? You’ll get blank output—names must match exactly! | 
|  | 337 | +
 | 
|  | 338 | +### 3.6 Running and Testing | 
|  | 339 | + | 
|  | 340 | +- **Purpose**: Check if binding works—type names and see them confirmed! | 
|  | 341 | +- **Steps**: | 
|  | 342 | + 1. **Run It**: | 
|  | 343 | + - Right-click `FormDataBindingApplication.java` → Run As → Spring Boot App. | 
|  | 344 | + - Console: `Tomcat started on port(s): 8080`—server’s ready! | 
|  | 345 | + 2. **Test It**: | 
|  | 346 | + - **Step 1**: Go to `http://localhost:8080/showStudentForm`. | 
|  | 347 | + - See: "Student Form" with two text boxes and a "Submit" button. | 
|  | 348 | + - **Step 2**: Type "James" in First Name, "Gosling" in Last Name → Click Submit. | 
|  | 349 | + - Page: "Student is confirmed" with "First Name: James" and "Last Name: Gosling". | 
|  | 350 | + - Console: `Student: James Gosling`. | 
|  | 351 | +- **Full Flow**: | 
|  | 352 | + - `GET /showStudentForm` → `showForm()` → Adds empty `Student` to model → `student-form.html`. | 
|  | 353 | + - Submit → `POST /processStudentForm` → `processForm()` binds data to `Student`, logs it → `student-confirmation.html`. | 
|  | 354 | +- **Troubleshooting**: | 
|  | 355 | + - **Blank Page?**: Check `th:field` names match `Student` fields. | 
|  | 356 | + - **404?**: Ensure files are in `/templates/` (e.g., `student-form.html`). | 
|  | 357 | + - **No Console Output?**: Verify `logger.info` syntax. | 
|  | 358 | + | 
|  | 359 | +>[!TIP] | 
|  | 360 | +>Change "James" to "Jane"—refresh and see it update instantly with DevTools! | 
|  | 361 | +
 | 
|  | 362 | +--- | 
|  | 363 | + | 
|  | 364 | +## 4. What’s Next | 
|  | 365 | + | 
|  | 366 | +- **Next Session**: **9.5 - Spring MVC - Form Data Binding - Dropdown List**—extend binding to dropdowns for picking options—more form fun awaits! | 
|  | 367 | + | 
|  | 368 | +>[!TIP] | 
|  | 369 | +>You’ve bound text boxes—next, tackle dropdowns like a pro! | 
|  | 370 | +
 | 
|  | 371 | +--- | 
0 commit comments