Monday, October 19, 2009

Recipe 3.12. Handling Unchecked Checkboxes










Recipe 3.12. Handling Unchecked Checkboxes




Problem



You need to ensure that a Boolean ActionForm
property, corresponding to an HTML checkbox, is set to
false when the checkbox is unchecked.





Solution



Create a checkbox input field that uses JavaScript to set the value
of a hidden Boolean field. Use the logic:equal tag
to set the checked property of the checkbox if the
value for the hidden field is true. The
JSP page (checkbox_test.jsp) in Example 3-18 uses this approach to guarantee a true or
false value is always submitted.




Example 3-18. Guaranteeing checkbox settings

<%@ page contentType="text/html;charset=UTF-8" 
language="java" %>
<%@ taglib uri="http://jakarta.apache.org/struts/tags-html"
prefix="html" %>
<%@ taglib uri="http://jakarta.apache.org/struts/tags-logic"
prefix="logic" %>
<html>
<head>
<title>Struts Cookbook - Chapter 4 : Checkbox Test</title>
</head>
<body>
<html:form method="get" action="/ProcessCheckbox">
<input type="checkbox" name="foo_"
onclick="javascript:elements['foo'].value=this.checked;"
<logic:equal name="CheckboxForm" property="foo" value="true">
checked
</logic:equal>
>
<html:hidden property="foo"/>
<html:submit/>
</html:form>
</body>
</html>







Discussion



For such a common little field, the HTML checkbox can cause trouble.
If a checkbox is unchecked and the form is submitted, no value for
that field will be sent in the request. Suppose you have a form with
one checkbox on it:



<html:form method="get" action="ProcessFoo">
<html:checkbox property="foo"/>
<html:submit/>
</html:form>




If the checkbox is checked, then the resultant request URL looks
something like this:



http://localhost/jsc-ch04/ProcessFoo?foo=on




When processed by Struts, your ActionForm is
populated by BeanUtils.populate( ) method. If
foo is a boolean property, its
value is set to true.



The problem occurs when you uncheck the checkbox with the intention
of setting the property value to false. If the checkbox is unchecked,
the resultant URL looks something like this:



http://localhost/jsc-ch04/ProcessFoo?




Where did the property value go? One would expect the request query
string to contain "foo=off" or
"foo=". Unfortunately, no request
parameter is generated for an unchecked checkbox. When
BeanUtils.populate( ) is called, it
doesn't know to set the property value.



This problem can usually be handled by implementing the

reset() method in your ActionForm. The Struts
request processor calls this method before the
ActionForm is populated. The method gives you a
chance to set the form properties to desired default values. If the
HTTP request doesn't contain a name/value pair for a
property, then the property retains the value set in the
reset( ) method. For checkboxes, set the value to
false, as shown here:



public void reset( ActionMapping mapping, 
HttpServletRequest request )
{
foo = false;
}




However, the reset( ) method
can't always solve the problem. If
you're using a form in session
scope in a wizard-style interface, then implementing

reset() will clear the form when you don't want
it to. You need an alternative that guarantees that a value will be
sent when the form is submitted. The Solution does that by
implementing two fields on the form. The actual form field
corresponding to the Boolean ActionForm property
isn't the checkbox, but is a hidden field generated
using the html:hidden tag. The checkbox is then
created using normal HTML (input type="checkbox").
A JavaScript onclick event handler is defined for
this control:



javascript:elements['foo'].value=this.checked;




When a user clicks the checkbox, the value of the hidden field is
set. If the checkbox is checked, the value is set to true; otherwise,
it is set to false. To ensure that the checkbox renders correctly
when the form is initially displayed, the
logic:equal tag is used to render the
checked attribute for the field.





See Also



This topic comes up fairly frequently on the

struts-user
mailing list. A good thread that discusses this topic is archived at
http://www.mail-archive.com/struts-user@jakarta.apache.org/msg93525.html.



If you are using the Struts html:multibox control
to render a set of checkboxes, a similar problem can occur when the
user clears all the values. An archived discussion on this topic can
be found at http://www.mail-archive.com/struts-user@jakarta.apache.org/msg96487.html.












    No comments:

    Post a Comment