When building dynamic web sites with lots of javascript UI components being created on the client, understanding how the web framework you’re using will process the request and what must be done to update fields accordingly is even more important.
Specifically, checkboxes have always been a pain to deal with. The gotcha with checkboxes are if a checkbox isn’t checked, the request doesn’t send the parameter so it requires some additional checks to detect that the user deselected something that was there to update the field accordingly. I’ve been playing around with the Stripes framework and ran into this issue.
With Stripes, you can render a checkbox using their JSP tag:
<stripes:checkbox checked="true" name="property1" value="yes"/> <stripes:checkbox checked="true" name="property2" value="no"/>
When the “checked” value is equal to “value” value, Stripes will render the checkbox as checked. So with the code shown, two checkboxes will be shown with the first checked and the second unchecked.
If a user reverses this by unchecking the first, checking the second, and submit the form, the HTTP request will only see that property2=no
. Before the form was submitted, “property1” had a value of “yes”. Now, “property1” won’t even appear in the request parameters, so we have to do special handling to check for the absent of the parameter to update “property1” to whatever value it should be when it is not checked.
In Spring MVC with form binding, checkboxes are dealt with a little differently. Using Spring MVC’s form JSP tag, you can do:
<form:checkbox path="property1" value="yes"/> <form:checkbox path="property2" value="no"/>
Assuming your command bean is named “person”, this will generate the following HTML:
<input name="person.property1" type="checkbox" value="yes"/> <input type="hidden" value="1" name="_person.property1"/> <input name="person.property2" type="checkbox" value="no"/> <input type="hidden" value="1" name="_person.property2"/>
As noted by the docs,
What you might not expect to see is the additional hidden field after each checkbox. When a checkbox in an HTML page is not checked, its value will not be sent to the server as part of the HTTP request parameters once the form is submitted, so we need a workaround for this quirk in HTML in order for Spring form data binding to work. The checkbox tag follows the existing Spring convention of including a hidden parameter prefixed by an underscore (“_”) for each checkbox. By doing this, you are effectively telling Spring that “the checkbox was visible in the form and I want my object to which the form data will be bound to reflect the state of the checkbox no matter whatâ€.
Spring MVC also provides a “checkboxes” tag which allows you to render a list of checkbox boxes without having to wrap the “checkbox” tag around a JSTL forEach.
Hopefully, that gives you some insight into how to work with checkboxes in Stripes and Spring MVC.
Short, but helpfull article.
Thanks for explaining this. I was banging my head against the wall about this stuff for a while.
“Now, “property1″ won’t even appear in the request parameters, so we have to do special handling to check for the [absence] of the parameter to update “property1″ to whatever value it should be when it is not checked.”
What is the special handling if one is not using Spring MVC? What if this is a list of checkboxes that matches a List of Objects in the ActionBean? Not only is the unchecked checkbox’s value not included in the request but the List object is not updated. It will be updated if a new value (a newly checked checkbox) is present, and even then only the new value is added to the list, nothing removed. Thoughts?