|
Recipe 3.11. Generating a Set of Related Radio ButtonsProblemYou want to generate a set of related radio buttons whose values are dynamically based on values retrieved from a Collection. SolutionExpose the set of values for the radio buttons as a Collection that can be iterated over using the logic:iterate tag. The idName attribute of the html:radio tag should be the same as the value of the id attribute of the iterate tag. Use the value attribute of the html:radio tag to specify a property of the idName object. The value of this property will be the value for the generated input type="radio" HTML control: <logic:iterate name="MyForm" property="values"> <html:radio property="beanValue" idName="loopVar" value="value"/> <bean:write name="loopVar" property="name"/> <br /> </logic:iterate> DiscussionRadio buttons are HTML controls in which one button can be selected at a time. Radio buttons are grouped together based on the name attribute of the HTML input tag. Like other HTML form input elements, the label for the control isn't part of the control itself. Developers label the control however they want using regular text. Typically, radio buttons are labeled with the text to the right of the input tag: <input type="radio" name="skill" value="1"/> Beginner <br /> <input type="radio" name="skill" value="2"/> Intermediate <br /> <input type="radio" name="skill" value="3"/> Advanced <br /> In some cases, the set of radio buttons in a group is dynamic. In other words, the radio buttons to render varies. Say you are taking a poll on programming languages and developer tools using a wizard-style interface. On the first page, you display a set of radio buttons where the poll takers pick their favorite language. On the second page, you present a set of related radio buttons where the poll takers pick their favorite IDE. The set of radio buttons for the IDE choices is dynamic, based on the language chosen on the first page. First, you need to define the form that will be used to hold the selected language and IDE. Since these are simple String properties, you can use a DynaActionForm: <form-bean name="DevPollForm" type="org.apache.struts.action.DynaActionForm"> <form-property name="language" type="java.lang.String" /> <form-property name="ide" type="java.lang.String" /> </form-bean> Next, create the Java class that holds the set of programming languages and corresponding IDEs, as shown in Example 3-14. The values are hardcoded here for demonstration purposes. The Struts LabelValueBean is used to hold the name/value pairs for the data. Example 3-14. Language choices JavaBeanpackage com.oreilly.strutsckbk; import java.util.*; import org.apache.struts.util.LabelValueBean; public class LanguageChoices { public LanguageChoices( ) { // create the set of languages languages = new ArrayList( ); languages.add(createBean("Java")); languages.add(createBean("C#")); languageIdeMap = new HashMap( ); // create the set of Java IDEs LabelValueBean[] javaIdes = new LabelValueBean[] { createBean("Eclipse"), createBean("NetBeans"), createBean("JDeveloper"), createBean("IDEA") }; // create the set of C# IDEs LabelValueBean[] csharpIdes = new LabelValueBean[] { createBean("SharpDevelop"), createBean("Visual Studio") }; // relate the language and IDEs languageIdeMap.put("Java", javaIdes); languageIdeMap.put("C#", csharpIdes); } private LabelValueBean createBean(String name) { return new LabelValueBean(name, name); } public Map getLanguageIdeMap( ) { return languageIdeMap; } public List getLanguages( ) { return languages; } private List languages; private Map languageIdeMap; } The first JSP page (lang_poll_1.jsp), shown in Example 3-15, renders the form containing the radio buttons for the language choice. Example 3-15. Generating related radio buttons via Struts tags<%@ page contentType="text/html;charset=UTF-8" language="java" %> <%@ taglib uri="/WEB-INF/struts-bean.tld" prefix="bean" %> <%@ taglib uri="/WEB-INF/struts-html.tld" prefix="html" %> <%@ taglib uri="/WEB-INF/struts-logic.tld" prefix="logic" %> <html> <head> <title>Struts Cookbook - Developer Poll</title> </head> <body> <jsp:useBean scope="application"/> <html:form action="ProcessLanguageChoice"> What's your favorite programming language? <p> <logic:iterate name="languageChoices" property="languages"> <html:radio property="language" idName="lang" value="value"/> <bean:write name="lang" property="label"/><br /> </logic:iterate> </p> <html:submit value="Next >>"/> </html:form> </body> </html> The LanguageChoices object is placed in application scope using the jsp:useBean standard JSP tag. Alternatively, this object could have been placed in scope using an Action or with a Struts plug-in. After the bean is instantiated, the form is created. The logic:iterate tag loops over the Language property of the LanguageChoices bean. This property is a java.util.List of org.apache.struts.util.LabelValueBeans. The LabelValueBean class mates a String label and a String value. The label is accessed by the label property and the value by the value property. In this example, the label and value are the same. In a real-world application, the value would probably be some sort of identity value, usually different from the displayed text. The logic:iterate tag exposes each LabelValueBean in the list as a scoped variable specified by the id attribute: "lang". The html:radio tag creates the actual input type="radio" HTML element. The property attribute identifies the name of the property of the ActionForm that will receive the value of the radio button. The idName attribute identifies the bean that contains the radio button value; in other words, the value exposed by the logic:iterate tag: "lang".
After creating the radio button, the label for the button is generated using the bean:write tag. This tag is used to render the label property from the LabelValueBean (lang). Example 3-16 shows the source that is generated from the JSP page in Example 3-15. Example 3-16. Generated source for lang_poll_1.jsp<html> <head> <title>Struts Cookbook - Developer Poll</title> </head> <body> <form name="DevPollForm" method="post" action="/jsc-ch03/ProcessLanguageChoice.do"> What's your favorite programming language? <p> <input type="radio" name="language" value="Java"> Java<br /> <input type="radio" name="language" value="C#"> C#<br /> </p> <input type="submit" value="Next >>"> </form> </body> </html> The second page of the poll asks the poll taker to choose a favorite IDE. The choices are based on the programming language selected on the first page. Like the first page, the choices are rendered as a set of radio buttons. Though the second page, shown in Example 3-17, is similar to the first page, this page uses a JSTL c:forEach loop. Example 3-17. Generating related radio buttons via JSTL<%@ page contentType="text/html;charset=UTF-8" language="java" %> <%@ taglib uri="/WEB-INF/struts-html.tld" prefix="html" %> <%@ taglib uri="http://java.sun.com/jstl/core" prefix="c" %> <html> <head> <title>Struts Cookbook - Developer Poll</title> </head> <body> Favorite Language: <b><c:out value="${DevPollForm.language}"/></b> <html:form action="ProcessIdeChoice"> What's your favorite IDE? <p> <c:forEach var="langIde" items="${languageChoices.languageIdeMap[DevPollForm.map.language]}"> <html:radio property="ide" idName="langIde" value="value"/> <c:out value="${langIde.label}"/><br /> </c:forEach> </p> <html:submit value="Next >>"/> </html:form> </body> </html>
The html:radio tag is used just as it was on the first page shown in Example 3-15. Though c:forEach is used instead of logic:iterate, you can use the idName attribute of the radio tag. When using JSTL in this way, the idName should be the same as the value for the var attribute of the JSTL c:forEach tag. See AlsoTed Husted has some great Struts tips at http://www.husted.com/struts/tips. Specifically, a discussion on the intricacies of the using radio buttons can be found at http://www.husted.com/struts/tips/016.html. |
|