分享

Dynamic checkboxes with Struts

 魔戒 2005-11-14

Dynamic checkboxes with Struts

Easily create checkboxes with dynamically selected elements

developerWorks
Document options
Set printer orientation to landscape mode

Print this page

Email this page

E-mail this page

Document options requiring JavaScript are not displayed

Discuss

Sample code


Rate this page

Help us improve this content


Level: Intermediate

Danilo Gurovich (dan@gurovich.com), Principal Engineer, Earthlink Inc.

25 Oct 2005

Struts Recipes co-author Danilo Gurovich picks up where George Franciscus left off with an easy-to-follow Struts recipe for creating dynamically selected checkboxes.

In user interface design, the checkbox group isn‘t as popular as its cousin, the multi-line selectbox. They both basically do the same thing; that is, they choose a collection of options mapped to a single name attribute. When used in groups, checkboxes actually perform the same function as the multi-line selectboxes, but they take up a little more screen real estate. This can be beneficial when you want the user to be able to view all the choices before selecting one or several of them.

While the multi-line selectbox typically provides a better look and feel when the choices are limited, a group of checkboxes is the better choice for any enterprise application where selection boxes must be rendered dynamically and contain preselection functionality. Fortunately, creating a group of dynamic checkboxes is easy to do with the Struts framework.

In this article, I show you a simple recipe using the Struts <html:multibox/> and <logic:iterate/> tags to present a number of items in an application‘s view layer, in this case a Java™ Server Page (JSP).

I‘ll start by using checkbox elements to show a simple String[] array of mountain peaks in the Himalayas. Then, I‘ll create another String[] array of selectedMountains to represent the checkboxes that have been selected. The preselection of the checkboxes will occur at the intersection of the two arrays. If the selectedMountains initial array is empty, all checkboxes will initially appear unchecked.

See Download for the complete example source code. You should have everything you need to follow along. See Resources if you need to download the Struts framework.

Creating dynamic checkboxes

The recipe for creating dynamic checkboxes consists of three major pieces:

  • A form bean that holds a String[] array of checkboxes and a String[] array of selected checkboxes

  • A JSP with a form that shows the checkboxes in the state you require

  • A simple Action class to go from the form page to the display page

Note that the "Himalayas" example is very simple. The fields used to populate a checkbox should come from a more sophisticated model, such as one that could identify the user and choose the fields to show and then precheck any that a business object may deem necessary. I‘ve used a simple model to better demonstrate Struts‘s UI functionality. The code samples use the JSP scripting language where appropriate for clarity.



Back to top


Step 1. Create the form bean

I‘ll start by creating a Struts form bean that contains the information needed to populate the checkboxes. Note that TestForm.java in Listing 1 includes getters and setters for the two example String[] array variables. The array mountains represents all of the checkboxes for the example, and the array selectedMountains represents the checked elements preselected to show in the browser.

In addition to representing the initially selected checkboxes, selectedMountains also represents checkboxes checked by the user when the form is processed. (It represents only the final checked elements.) When the page is requested, the checkboxes are displayed. As I iterate over them, any checkbox element that matches selectedMountains is checked.

Listing 1 shows the complete code for TestForm.java:


Listing 1. TestForm.java


package com.strutsrecipes;

import javax.servlet.http.HttpServletRequest;
import org.apache.struts.action.ActionError;
import org.apache.struts.action.ActionErrors;
import org.apache.struts.action.ActionForm;
import org.apache.struts.action.ActionMapping;

public final class CheckboxTestForm
extends ActionForm {

// Instance Variables

/*Mountains "pre-selected"...*/
private String[]
selectedMountains
=
{"Everest","K2","Lhotse"};

/*the ten tallest Mountains to iterate through*/
private String[]
mountains
=
{"Everest","K2","Kangchenjunga","Lhotse",
"Makalu","Kangchenjunga South",
"Lhotse Middle","Kangchenjunga West",
"Lhotse Shar","Cho Oyu"};

/*Getter for selectedMountains*/
public String[] getSelectedMountains() {
return this.selectedMountains;
}

/*Setter for selectedMountains*/
public void setSelectedMountains(String[] selectedMountains) {
this.selectedMountains = selectedMountains;
}

/*Getter for the mountains*/
public String[] getMountains() {
return this.mountains;
}

/*Setter for the mountains*/
public void setMountains(String[] mountains) {
this.mountains = mountains;
}
}



Back to top


Step 2. Write the JSP code

Next, I write the JSP code for the page that propagates TestForm.java‘s information to the view layer. When writing this code, it is essential to import the corresponding Struts taglibs onto the JSP. The JSP code in Listing 2 is for a simple form that displays checkboxes with the appropriate ones checked:


Listing 2. The JSP with the form

<%@taglib uri="http://jakarta./struts/tags-html" prefix="html"%>
<%@taglib uri="http://jakarta./struts/tags-bean" prefix="bean"%>
<%@taglib uri="http://jakarta./struts/tags-logic" prefix="logic"%>

<%-- html code, etc... -->

<html:form
action="/FormAction" 
name="testForm"
type="com.strutsrecipes.CheckboxTestForm">

<h4><bean:message key="testForm.instruction"/></h4>

<logic:iterate name="testForm" 
property="mountains" 
id="mountain">

<%-- create the checkbox and selected attribute -->
<html:multibox property="selectedMountains">
<bean:write name="mountain"/>
</html:multibox>

<%-- create the label, note that "br" tag will format it vertically -->
<bean:write name="mountain"/><br/>

</logic:iterate>

<br/>
<html:submit/><html:reset/>

</html:form>

<%-- some more html code, etc... -->

Notice that I‘m using the Struts <bean:message/> tag for text, the <html:multibox/> for the HTML checkboxes, and the <logic:iterate/> tag to iterate through arrays and create everything. My form bean is instantiated on the JSP by the <html:form/> tag.

My next step is to iterate through the mountains field in the <logic:iterate/> tag. In so doing, I create a variable ( mountain) to populate the checkbox and give it a label using the <bean:write/> tag. To create the selected attribute in the checkbox, I‘ll again use the <logic:iterate/> and <html:multibox/> tags. The property attribute in the <html:multibox/> tag is populated by the selectedMountains field. The selectBox is checked when selectedMountains equals mountain.



Back to top


Step 3. Write the Action class

My final step is to write the Action class. Not much is happening in Listing 3 compared to the others. All I do is get the String[] array of selectedMountains and make it available to the page:


Listing 3. The Action for the form


import org.apache.struts.action.Action;
import org.apache.struts.action.ActionForm;
import org.apache.struts.action.ActionForward;
import org.apache.struts.action.ActionMapping;

import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;

/**
* A simple Action for Checkbox test.
*
* @author Danilo Gurovich
*/
public final class CheckboxTestAction
extends Action {
// -------------------------- OTHER METHODS --------------------------

/**
* The execute method
*
* @param mapping ActionMapping
* @param form CheckboxTestForm
* @param request HttpServletRequest
* @param response HttpServletRespons
* @return success to the confirmation page
* @throws ServletException not thrown, but could be!
* @throws Exception ditto.
*/
public ActionForward execute(ActionMapping mapping,
ActionForm form,
HttpServletRequest request,
HttpServletResponse response)
throws ServletException, Exception {

// Extract attributes needed
String[] selectedMountains =
((CheckboxTestForm) form).getSelectedMountains()
;

System.out.println("htmlString RETURNED*\n" +
selectedMountains.toString());

//Save the htmlString in the session for later...
HttpSession session = request.getSession();
session.setAttribute(CheckboxConstants.MOUNTAINS, selectedMountains);

return (mapping.findForward("success"));
}
}



Back to top


Scaling the Himalayas

And with that, I‘m finished with the "heavy lifting" and I‘m almost ready to show off my fine work! The user may now submit the JSP form and review the results in the corresponding page referenced by the Action class. The code snippet in Listing 4 shows the list of boxes checked by the user in the form of a simple JSP:


Listing 4. The results of the checked boxes


<%@taglib uri="http://jakarta./struts/tags-html" prefix="html"%>
<%@taglib uri="http://jakarta./struts/tags-bean" prefix="bean"%>
<%@taglib uri="http://jakarta./struts/tags-logic" prefix="logic"%>

<%-- html code, etc... -->

<logic:iterate id="mountain" property="mountains" name="testForm">
<bean:write name="mountain"/><br/>
</logic:iterate>
<hr size=5 color="black"/>

<%-- some more html code, etc... -->



Back to top


How the recipe works

The key to this recipe is the way the fields in the form bean are propagated to the page. A look at the pertinent JSP code helps clarify this. Once the form bean is instantiated:


<html:form action="/FormAction" 
name="testForm"
type=" com.strutsrecipes.CheckboxTestForm">

the next step is to create a checkbox for every mountain in the mountains variable of the Java class. To do this, I have to iterate through the String[] array like this:


<logic:iterate id="mountain"
property="mountains" 
name="testForm">

With the <logic:iterate> tag, I call the getMountains() method in the testForm bean. It iterates through this array and return each value as a mountain[] pageContext()-level String array variable (that is, id="mountain") that I have named.

Here you can see what affects the actual <html:multibox/> tag and how it will be displayed:


<html:multibox property="selectedMountains">
<bean:write name="mountain"/>
</html:multibox>
<bean:write name="mountain"/><br/>

Notice that the property attribute is filled with selectedMountains, which is my checked variable. When this value corresponds with the <html:multibox/> value (that is, the <bean:write/> inside the multibox tags), it appears as checked when the form is rendered. If the user checks or unchecks the form, the new selectedMountains value(s) is sent to the Action class for processing. The second <bean:write/> tag in this iteration creates the label that the tag uses, followed by a <br/> tag to make the view show the tags in a long column.



Back to top


Extending the recipe

You can extend the dynamic checkbox recipe to create different labels for your checkboxes by using the Struts LabelValueBean class instead of a simple String[] array. You start by adding the LabelValueBeans to a java.util.List. You then iterate through the list and extract the LabelValueBeans labels and values to their appropriate places. This slightly more complex recipe achieves the same results as the dynamic checkbox recipe, but with results more applicable to real-world UI design. Listing 5 shows the extended dynamic checkbox recipe:


Listing 5. Adding labels to dynamic checkboxes


<logic:iterate id="mountainlb" 
property="mountainslb" 
name="testForm">

<bean:define id="mountainbean" 
name="mountainlb
"type="org.apache.struts.util.LabelValueBean"/>

<html:multibox property="selectedMountains">
<bean:write name="mountainbean" 
property="value"/>
</html:multibox>
<bean:write name="mountainbean" 
property="label"/><br/>

</logic:iterate>

Note that the big change here is using <bean:define/> to create the LabelValueBean as it iterates. You then use <bean:write/> to write out the properties of each mountainbean (that is, the getLabel() and getValue() methods of the org.apache.struts.util.LabelValueBean class).



Back to top


In conclusion

Struts provides excellent support for dynamically rendering and preselecting checkboxes. This recipe was one of the reasons that I co-authored Struts Recipes -- at the time I had found lots of theory and server-side information related to the Struts framework, but UI programming was mostly ignored, or at best glossed over. After searching high and low for a recipe to create checkboxes using Struts, I gave up and wrote my own. By combining various pieces, I was able to build a dynamic checkbox system that suited me.

You‘ll notice that the code sample is set up to be useful as a test bed for different UI widgets and layouts ideas. In fact, I used it for most of the UI examples in the book, just tweaking the Action class and my model to fit the needs of the recipe. I‘ve also used it in development to test different ideas without spending too much time coding up something inside the application I was working on.




Back to top


Download

Description Name Size Download method
Sample code j-sr3-source.zip 3249 KB FTP
Information about download methods Get Adobe® Reader®


Back to top


Resources

Learn
  • "Struts- Velocity integration" (George Franciscus, developerWorks, September 2005): The Velocity Template Engine is a fast, flexible alternative to Java ServerPages in Struts.

  • "Integrating Struts, Tiles, and JavaServer Faces" (Srikanth Shenoy and Nithin Mallya, developerWorks, September 2003): Harness the front-end power of JavaServer Faces, the formatting strength of Tiles, and the flexibility of the Struts controller tier.

  • Struts Recipes (George Franciscus and Danilo Gurovich; Manning, 2004): A popular compendium of Struts recipes and best practices.

  • Struts In Action (Ted Husted, Cedric Dumoulin, George Franciscus, David Winterfeldt; Manning, 2002): A comprehensive resource for professional Struts developers.

  • The Java technology zone: Find articles about every aspect of Java programming.


Get products and technologies

Discuss

    本站是提供个人知识管理的网络存储空间,所有内容均由用户发布,不代表本站观点。请注意甄别内容中的联系方式、诱导购买等信息,谨防诈骗。如发现有害或侵权内容,请点击一键举报。
    转藏 分享 献花(0

    0条评论

    发表

    请遵守用户 评论公约

    类似文章 更多