Reputation: 234
I'm using Spring MVC and I generate a form which the user modifies/completes and then sends back via POST. Fields that are Integers (HTML radio buttons) or boolean (HTML checkbox) work just fine (the Java object is correctly populated) but I have several checkboxes with the same name and multiple values; I would like these to be stored in the Java object's List structure; I have followed web examples but it doesn't seem to work. Any ideas?
Controller:
@RequestMapping("/generateTest")
public String generateTest(Model model) {
model.addAttribute("grades", subject.getGrades());
model.addAttribute("testGenRequest", new TestGenerationRequest());
return "generatetest";
}
@RequestMapping(value = "/generateTest/download.pdf", method = RequestMethod.POST)
public String generateTestDownload(@ModelAttribute("testGenRequest") TestGenerationRequest testGen, BindingResult result, Model model) {
if (result.hasErrors()) {
return "redirect:/generateTest";
}
String[] suppressedFields = result.getSuppressedFields();
if (suppressedFields.length > 0) {
throw new RuntimeException("Attempting to bind disallowed fields: " + StringUtils.arrayToCommaDelimitedString(suppressedFields));
}
model.addAttribute("countedgrades", testGen.getSelectedGrades().size());
model.addAttribute("countedgrades", testGen.getSelectedGrades().size());
return "pageToTestDisplayOfFormInput";
}
@InitBinder
public void initialiseBinder(WebDataBinder binder) {
binder.setAllowedFields("testNum", "selectedGrades", "orientation", "includeRepro");
}
View (JSP) - displays to user as expected; content chopped to show only the field that isn't working (selectedGrades):
<c:url var="actionURL" value="/generateTest/download.pdf"/>
<form:form method="POST" modelAttribute="testGenRequest" action="${actionURL}" class="form-horizontal" enctype="multipart/form-data" id="testForm">
<form:errors path="*" cssClass="alert alert-danger" element="div"/>
<fieldset>
<div class="col-sm-10" id="whichGrades">
<c:forEach items="${grades}" var="grade">
<label class="checkbox-inline btn btn-default" for="whichGrade-${grade.grade}">
<form:checkbox id="whichGrade-${grade.grade}" value="${grade.grade}" path="selectedGrades"/>
${grade.grade}
</label>
</c:forEach>
</div>
</div>
</fieldset>
<div class="col-sm-offset-2 col-sm-10">
<button type="submit">Confirm</button>
</form:form>
Model attribute backing object TestGenerationRequest.class:
import com.fasterxml.jackson.annotation.JsonIgnore;
import java.io.Serializable;
import java.util.ArrayList;
import java.util.List;
import javax.xml.bind.annotation.XmlAccessType;
import javax.xml.bind.annotation.XmlAccessorType;
import javax.xml.bind.annotation.XmlRootElement;
import org.springframework.stereotype.Component;
@Component
@XmlRootElement(name = "testGenerationRequest")
@XmlAccessorType(XmlAccessType.FIELD)
public class TestGenerationRequest implements Serializable {
private final static long serialVersionUID = 934343334534L;
@JsonIgnore
public static final int FORMAT_PORTRAIT = 1;
@JsonIgnore
public static final int FORMAT_LANDSCAPE = 2;
private int testNum;
private List<String> selectedGrades;
private int orientation;
private boolean includeRepro;
public TestGenerationRequest() {
super();
selectedGrades = new ArrayList<String>();
this.orientation = TestGenerationRequest.FORMAT_PORTRAIT;
this.includeRepro = false;
}
public int getTestNum() {
return testNum;
}
public void setTestNum(int testNum) {
this.testNum = testNum;
}
public int getOrientation() {
return orientation;
}
public void setOrientation(int orientation) {
this.orientation = orientation;
}
public boolean isIncludeRepro() {
return includeRepro;
}
public void setIncludeRepro(boolean includeRepro) {
this.includeRepro = includeRepro;
}
public List<String> getSelectedGrades() {
return selectedGrades;
}
public void setSelectedGrades(List<String> selectedGrades) {
this.selectedGrades = selectedGrades;
}
}
Any help would be appreciated. The desired outcome is that the TestGenerationRequest handled in the controller's generateTestDownload method contains a List with elements corresponding to the checkboxes that were ticked in the view by the user (these could be either integers or Strings). The actual outcome at present is that selectedGrades is always empty (0 elements). Thanks.
Upvotes: 0
Views: 1822
Reputation: 234
I found the solution, for the benefit of future readers.
In the view, the had a enctype="multipart/form-data" which was not required; remove this and everything works properly!
Upvotes: 2