Recipe3.11.Generating a Set of Related Radio Buttons


Recipe 3.11. Generating a Set of Related Radio Buttons

Problem

You want to generate a set of related radio buttons whose values are dynamically based on values retrieved from a Collection.

Solution

Expose 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"/>   &nbsp;   <bean:write name="loopVar" property="name"/>   <br /> </logic:iterate>

Discussion

Radio 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 JavaBean
package 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"/>          &nbsp;<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".

The idName attribute was added with the release of Struts 1.1. With Struts 1.0, the value for the radio button had to be rendered using a runtime expression:

<html:radio property="language" value="<%= lang.getValue(  ) %>"/>


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">          &nbsp;Java<br />                <input type="radio" name="language" value="C#">          &nbsp;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"/>          &nbsp;<c:out value="${langIde.label}"/><br />       </c:forEach>       </p>       <html:submit value="Next >>"/>   </html:form> </body> </html>

Accessing Complex Properties with JSTL

More interesting in Example 3-17 is how the JSTL expression language (EL) is used to retrieve the collection of IDEs for the chosen language:

${languageChoices.languageIdeMap[DevPollForm.map.language]}

The power of EL allows you to access normal JavaBean properties as well as mapped properties in almost any combination. To understand how the expression is evaluated, let's examine how it would be done in Java:

// get the language-ide map Map ideMap = languageChoices.getLanguageIdeMap(  ); // get the selected language from the form bean DynaActionFrom form =   (DynaActionForm) session.getAttribute("DevPollForm"); String language = form.getMap( ).get("language"); // get the list of IDEs from the language-ide map List ides = (List) map.get(language);

DynaActionForms expose their internal table of name/value pairs via the map property. This allows you to retrieve the chosen language from the DevPollForm dynamic form bean.


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 Also

Ted 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.



    Jakarta Struts Cookbook
    Jakarta Struts Cookbook
    ISBN: 059600771X
    EAN: 2147483647
    Year: 2005
    Pages: 200

    flylib.com © 2008-2017.
    If you may any questions please contact us: flylib@qtcs.net