I used ModelAttribute to bind object in Spring web application.
Once I notice that, in case an object has an boolean value A is true, its value will not be updated if we uncheck A's checkbox.
For example, I have a Lesson object which has the attribute "active" = true. In "Edit Lesson" view, I make a checkbox which bind into "active". Things work well if the checkbox is checked (the binding object reflect the changes), but the object lesson will not change if we un-check the checkbox.
Further study tells me that's because the checkbox value may not get submitted by browser (this is an in-design of HTML). So I have to use the ugly request.getParameter
to check if the value is set.
I just come by this question, and I see that asp.net mvc provide a way to work around it more elegantly. I think Spring must provide something similarly. Does anyone know how to do that?
Following is my code:
Controller code:
@RequestMapping(value="/test", method = RequestMethod.POST)
public String processEditLesson(@Valid Lesson lesson, BindingResult bindingResult, Model model) {
System.out.println("Lesson is active: " + lesson.isActive()); // still "true" even if the checkbox is unset
// Current work-around
String isActive = request.getParameter("active");
if (StringUtils.isNotNullOrEmpty(isActive)) {
lesson.setActive(true);
} else {
lesson.setActive(false);
}
...
}
View code:
<form id="lesson" class="EditorForm" action="${rc.getContextUrl('/test.html')}" method="post" >
<fieldset>
<legend><@spring.message code="lesson.edit"/></legend>
<@spring.formHiddenInput "lesson.id" />
<@spring.formHiddenInput "lesson.studio.id" />
<div class="Entry">
<label for="name"><@spring.message code="lesson.message"/></label>
<@spring.formInput "lesson.message" />
<span class="ErrorMessage"><@spring.showErrors "<br/>" /></span>
</div>
<input type="checkbox" name="active" checked="checked" />
<label for="active">${rc.getMessage('lesson.active')}</label>
<input type="submit" value="<@spring.message code='common.update' />" />
</fieldset>
</form>
Spring has a built in workaround.
Simply add this additional hidden field to the form:
<input type="hidden" value="on" name="_active"/>
The parameter with a leading underscore is some kind of marker, to indicate the existence of a checkbox parameter with the same name, but without the underscore.
Spring should now set lesson.active
to false if only _active=on
is submitted.