Spring MVC: <form:select> option won't stay selected
select, spring-mvc
Solution
Your model includes an attribute `title` that refers to a `Title` class. This is not the same `title` you are referring to in your form, which is actually a `titleId`. Since the `titleId` is not part of the `modelAttribute`, it should be excluded from the `<form:xxx>` tags. You are going to need to use a plain-old `<select>` tag to pass the selected `titleId` back to the controller for processing. Unfortunately with a `<select>` tag, you can't just set the value attribute with JSTL, so you have to conditionally set the `seelcted` attribute of the option, based on the `titleId` value (if it is set). If `titleList` is a simple list of `Title` objects, you can create your `<select>` tag this way:
<select id="titleInput" name="titleId">
<option value=""></option>
<c:forEach items="${titleList}" var="title">
<c:when test="${title.titleId== titleId}">
<option value="${title.titleId}" selected>${title.titleName}</option>
</c:when>
<c:otherwise>
<option value="${title.titleId}" >${title.titleName}</option>
</c:otherwise>
</c:forEach>
</select>
In your controller, the `@RequestParam` annotation will pull the `titleId` out of the submitted data. Since it is not part of the `modelAttribute`, you need to make sure this gets added as a model attribute:
...
if (result.hasErrors()) {
if (titleId != null) {
model.addAttribute("titleId", titleId); // <--This line added
model.addAttribute("titleList", titleService.getAll());
Title title = titleService.get(titleId);
teacher.setTitle(title);
model.addAttribute("teacher", teacher);
return "addTeacher";
}
else {
model.addAttribute("titleList", titleService.getAll());
return "addTeacher";
}
}
...
Hopefully we got it this time.
Problem
I have a simple form for adding a new teacher. I'm using Spring `<form:select>` in my view to show a list of teacher's titles, but when I select an option without entering teacher's first and/or last name, since I'm doing validation of all three fields, when the page loads after submit, previously selected option gets lost and "Select title" text appears again. This is controller: ``` @RequestMapping(value="/add", method = RequestMethod.POST) public String postAddTeacher(@RequestParam(value = "title") Integer titleId, @Validated(Teacher.TeacherChecks.class) @ModelAttribute("teacherAttribute") Teacher teacher, BindingResult result, Model model) { logger.debug("Received request to add new teacher"); if (result.hasErrors()) { if (titleId != null) { model.addAttribute("titleList", titleService.getAll()); Title title = titleService.get(titleId); teacher.setTitle(title); model.addAttribute("teacher", teacher); return "addTeacher"; } else { model.addAttribute("titleList", titleService.getAll()); return "addTeacher"; } } else { teacherService.add(titleId, teacher); return "success/addTeacherSuccess"; } } ``` This is view: ``` <c:url var="saveUrl" value="/essays/main/teacher/add" /> <form:form modelAttribute="teacherAttribute" method="POST" action="${saveUrl}"> <form:errors path="*" cssClass="errorblock" element="div" /> <form:label path="title"></form:label> <form:select path="title" id="titleSelect"> <form:option value="" label="Select title" /> <form:options items="${titleList}" itemValue="titleId" itemLabel="titleDescription" /> </form:select> <form:errors path="title" cssClass="error"/> <form:label path="firstName">First name:</form:label> <form:input path="firstName"/> <form:errors path="firstName" cssClass="error"/> <form:label path="lastName">Last name:</form:label> <form:input path="lastName"/> <form:errors path="lastName" cssClass="error"/> <input type="submit" value="Submit" /> </form:form> ``` Just in case this is Teacher bean: ``` @Id @GeneratedValue(strategy = IDENTITY) @Column(name = "TEACHER_ID", unique = true, nullable = false) private Integer teacherId; @NotNull(message = "Teacher's first name is null!", groups = TeacherChecks.class) @NotBlank(message = "Please enter teacher's first name!", groups = TeacherChecks.class) @Column(name = "FIRST_NAME", nullable = false, length = 50) private String firstName; @NotNull(message = "Teacher's last name is null!", groups = TeacherChecks.class) @NotBlank(message = "Please enter teacher's last name!", groups = TeacherChecks.class) @Column(name = "LAST_NAME", nullable = false, length = 50) private String lastName; @NotNull(message = "Please choose title!", groups = TeacherChecks.class) @Valid @ManyToOne(cascade = {CascadeType.PERSIST, CascadeType.MERGE}, fetch=FetchType.EAGER) @JoinColumn(name = "TITLE_FK", nullable = false) private Title title; @ManyToMany(mappedBy = "teachers") private Set<Activity> activities; public Teacher() { } // getters & setters ``` I would like to keep my selected option after page reloads. I though it will happen automatically, like when I enter a value into a text field, it stays there even after the page reloads. Can someone please help me with this? Is there a way to do that from the controller, or it has to be done in the view, and how? Update: I added `value="${teacherAttribute.title}"` to `<form:select>`, as @willOEM suggested, but it still doesn't work. Now it looks like this: ``` <form:select path="title" id="titleSelect" value="${teacherAttribute.title}"> <form:option value="" label="Select title" /> <form:options items="${titleList}" itemValue="titleId" itemLabel="titleDescription" /> </form:select> ```