Selection Tags
JSF has seven tags for making selections:
- h:selectBooleanCheckbox
- h:selectManyCheckbox
- h:selectOneRadio
- h:selectOneListbox
- h:selectManyListbox
- h:selectOneMenu
- h:selectManyMenu
Table 4–23 shows examples of each tag.
Table 4–23. Selection Tag Examples
Tag |
Generated HTML |
Examples |
h:selectBooleanCheckbox |
<input type="checkbox"> |
|
h:selectManyCheckbox |
<table> ... <label> <input type="checkbox"/> </label> ... </table> |
|
h:selectOneRadio |
<table> ... <label> <input type="radio"/> </label> ... </table> |
|
h:selectOneListbox |
<select> <option value="Cheese"> Cheese </option> ... </select> |
|
h:selectManyListbox |
<select multiple> <option value="Cheese"> Cheese </option> ... </select> |
|
h:selectOneMenu |
<select size="1"> <option value="Cheese"> Cheese </option> ... </select> |
|
h:selectManyMenu |
<select multiple size="1"> <option value="Sunday"> Sunday </option> ... </select> |
The h:selectBooleanCheckbox is the simplest selection tag—it renders a checkbox you can wire to a boolean bean property. You can also render a set of checkboxes with h:selectManyCheckbox.
Tags whose names begin with selectOne let you select one item from a collection. The selectOne tags render sets of radio buttons, single-select menus, or listboxes. The selectMany tags render sets of checkboxes, multiselect menus, or listboxes.
All selection tags share an almost identical set of attributes, listed in Table 4–24.
Table 4–24. Attributes for h:selectBooleanCheckbox, h:selectManyCheckbox, h:selectOneRadio, h:selectOneListbox, h:selectManyListbox, h:selectOneMenu, and h:selectManyMenu
Attributes |
Description |
enabledClass, disabledClass |
CSS class for enabled or disabled elements—for h:selectOneRadio and h:selectManyCheckbox only. |
selectedClass, unselectedClass |
CSS class for selected or unselected elements—for h:selectManyCheckbox only. |
layout |
Specification for how elements are laid out: lineDirection (horizontal) or pageDirection (vertical)—for h:selectOneRadio and h:selectManyCheckbox only. |
label |
A description of the component for use in error messages. |
collectionType |
(selectMany tags only) A string or a value expression that evaluates to a fully qualified collection class name, such as java.util.TreeSet. See "The value Attribute and Multiple Selections" on page 162. |
hideNoSelectionOption |
Hide any item that is marked as the "no selection option". See "The f:selectItem Tag" on page 153. |
binding, converter, converterMessage , requiredMessage , id, immediate, required, rendered, validator, validatorMessage , value, valueChangeListener |
Basic attributes.a |
accesskey, border, dir, disabled, lang, readonly, style, styleClass, size, tabindex, title |
HTML 4.0b—border is applicable to h:selectOneRadio and h:selectManyCheckbox only. size is applicable to h:selectOneListbox and h:selectManyListbox only. |
onblur, onchange, onclick, ondblclick, onfocus, onkeydown, onkeypress, onkeyup, onmousedown, onmousemove, onmouseout, onmouseover, onmouseup, onselect |
DHTML events.c |
Checkboxes and Radio Buttons
Two JSF tags represent checkboxes:
- h:selectBooleanCheckbox
- h:selectManyCheckbox
The h:selectBooleanCheckbox tag represents a single checkbox that you can wire to a boolean bean property. Here is an example:
In your JSF page, you do this:
<h:selectBooleanCheckbox value="#{form.contactMe}"/>
In your backing bean, provide a read-write property:
private boolean contactMe; public void setContactMe(boolean newValue) { contactMe = newValue; } public boolean getContactMe() { return contactMe; }
The generated HTML looks something like this:
<input type="checkbox" name="_id2:_id7"/>
You can create a group of checkboxes with h:selectManyCheckbox. As the tag name implies, you can select one or more of the checkboxes in the group. You specify that group within the body of h:selectManyCheckbox, either with one or more f:selectItem tags or one f:selectItems tag. See "Items" on page 153 for more information about those core tags. For example, here is a group of checkboxes for selecting colors:
The h:selectManyCheckbox tag looks like this:
<h:selectManyCheckbox value="#{form.colors}"> <f:selectItem itemValue="Red" itemLabel="Red"/> <f:selectItem itemValue="Blue" itemLabel="Blue"/> <f:selectItem itemValue="Yellow" itemLabel="Yellow"/> <f:selectItem itemValue="Green" itemLabel="Green"/> <f:selectItem itemValue="Orange" itemLabel="Orange"/> </h:selectManyCheckbox>
The checkboxes are specified with f:selectItem (page 153) or f:selectItems (page 155).
The h:selectManyCheckbox tag generates an HTML table element; here is the generated HTML for our color example:
<table> <tr> <td> <label for="_id2:_id14"> <input name="_id2:_id14" value="Red" type="checkbox"> Red</input> </label> </td> </tr> ... </table>
Each color is an input element, wrapped in a label for accessibility. That label is placed in a td element.
Radio buttons are implemented with h:selectOneRadio. Here is an example:
The value attribute of the h:selectOneRadio tag specifies the currently selected item. Once again, we use multiple f:selectItem tags to populate the radio buttons:
<h:selectOneRadio value="#{form.education}"> <f:selectItem itemValue="High School" itemLabel="High School"/> <f:selectItem itemValue="Bachelor's" itemLabel="Bachelor's"/> <f:selectItem itemValue="Master's" itemLabel="Master's"/> <f:selectItem itemValue="Doctorate" itemLabel=Doctorate"/> </h:selectOneRadio>
Like h:selectManyCheckbox, h:selectOneRadio generates an HTML table. Here is the table generated by the preceding tag:
<table> <tr> <td> <label for="_id2:_id14"> <input name="_id2:_id14" value="High School" type="radio"> High School </input> </label> </td> </tr> ... </table>
Besides generating HTML tables, h:selectOneRadio and h:selectManyCheckbox have something else in common—a handful of attributes unique to those two tags:
- border
- enabledClass
- disabledClass
- layout
The border attribute specifies the width of the border. For example, here are radio buttons and checkboxes with borders of 1 and 2, respectively:
The enabledClass and disabledClass attributes specify CSS classes used when the checkboxes or radio buttons are enabled or disabled, respectively. For example, the following picture shows an enabled class with an italic font style, blue color, and yellow background:
The layout attribute can be either lineDirection (horizontal) or pageDirection (vertical). For example, the following checkboxes on the left have a pageDirection layout and the checkboxes on the right are lineDirection:
Menus and Listboxes
Menus and listboxes are represented by the following tags:
- h:selectOneListbox
- h:selectManyListbox
- h:selectOneMenu
- h:selectManyMenu
The attributes for the preceding tags are listed in Table 4–24 on page 146, so that discussion is not repeated here.
Menu and listbox tags generate HTML select elements. The menu tags add a size="1" attribute to the select element. That size designation is all that separates menus and listboxes.
Here is a single-select listbox:
The corresponding listbox tag looks like this:
<h:selectOneListbox value="#{form.year}" size="5"> <f:selectItem itemValue="1900" itemLabel="1900"/> <f:selectItem itemValue="1901" itemLabel="1901"/> ... </h:selectOneListbox>
Notice that we've used the size attribute to specify the number of visible items. The generated HTML looks like this:
<select name="_id2:_id11" size="5"> <option value="1900">1900</option> <option value="1901">1901</option> ... </select>
Use h:selectManyListbox for multiselect listboxes like this one:
The listbox tag looks like this:
<h:selectManyListbox value="#{form.languages}"> <f:selectItem itemValue="English" itemLabel="English"/> <f:selectItem itemValue="French" itemLabel="French"/> <f:selectItem itemValue="Italian" itemLabel="Italian"/> <f:selectItem itemValue="Spanish" itemLabel="Spanish"/> <f:selectItem itemValue="Russian" itemLabel="Russian"/> </h:selectManyListbox>
This time we do not specify the size attribute, so the listbox grows to accommodate all its items. The generated HTML looks like this:
<select name="_id2:_id11" multiple> <option value="English">English</option> <option value="French">French</option> ... </select>
Use h:selectOneMenu and h:selectManyMenu for menus. A single-select menu looks like this:
h:selectOneMenu created the preceding menu:
<h:selectOneMenu value="#{form.day}"> <f:selectItem itemValue="1" itemLabel="Sunday"/> <f:selectItem itemValue="2" itemLabel="Monday"/> <f:selectItem itemValue="3" itemLabel="Tuesday"/> <f:selectItem itemValue="4" itemLabel="Wednesday"/> <f:selectItem itemValue="5" itemLabel="Thursday"/> <f:selectItem itemValue="6" itemLabel="Friday"/> <f:selectItem itemValue="7" itemLabel="Saturday"/> </h:selectOneMenu>
Here is the generated HTML:
<select name="_id2:_id17" size="1"> <option value="1">Sunday</option> ... </select>
The h:selectManyMenu tag is used for multiselect menus. That tag generates HTML, which looks like this:
<select name="_id2:_id17" multiple size="1"> <option value="1">Sunday</option> ... </select>
That HTML does not yield consistent results among browsers. For example, here is h:selectManyMenu on Internet Explorer (left) and Netscape (right):
Items
Starting with "Checkboxes and Radio Buttons" on page 148, we have used multiple f:selectItem tags to populate select components. Now that we are familiar with the visual appearance of selection tags, we take a closer look at f:selectItem and the related f:selectItems tags.
The f:selectItem Tag
You use f:selectItem to specify single selection items, like this:
<h:selectOneMenu value="#{form.condiments}"> <f:selectItem itemValue="Cheese" itemLabel="Cheese"/> <f:selectItem itemValue="Pickle" itemLabel="Pickle"/> <f:selectItem itemValue="Mustard" itemLabel="Mustard"/> <f:selectItem itemValue="Lettuce" itemLabel="Lettuce"/> <f:selectItem itemValue="Onions" itemLabel="Onions"/> </h:selectOneMenu>
The values—Cheese, Pickle, etc.—are transmitted as request parameter values when a selection is made from the menu and the menu's form is subsequently submitted. The itemLabel values are used as labels for the menu items. Sometimes you want to specify different values for request parameter values and item labels:
<h:selectOneMenu value="#{form.condiments}"> <f:selectItem itemValue="1" itemLabel="Cheese"/> <f:selectItem itemValue="2" itemLabel="Pickle"/> <f:selectItem itemValue="3" itemLabel="Mustard"/> <f:selectItem itemValue="4" itemLabel="Lettuce"/> <f:selectItem itemValue="5" itemLabel="Onions"/> </h:selectOneMenu>
In the preceding code, the item values are strings. "Binding the value Attribute" on page 161 shows you how to use different data types for item values.
In addition to labels and values, you can also supply item descriptions and specify an item's disabled state:
<f:selectItem itemLabel="Cheese" itemValue="#{form.cheeseValue}" itemDescription="used to be milk" itemDisabled="true"/>
Item descriptions are for tools only—they do not affect the generated HTML. The itemDisabled attribute, however, is passed to HTML. The f:selectItem tag has the attributes shown in Table 4–25.
Table 4–25. Attributes for f:selectItem
Attribute |
Description |
binding, id |
Basic attributesa |
itemDescription |
Description used by tools only |
itemDisabled |
Boolean value that sets the item's disabled HTML attribute |
itemLabel |
Text shown by the item |
itemValue |
Item's value, passed to the server as a request parameter |
value |
Value expression that points to a SelectItem instance |
escape |
true if special characters in the value should be converted to character entities (default), false if the value should be emitted without change |
noSelectionOption |
true if this item is the "no selection" option that, when selected, indicates that the user intends to made no selection |
As of JSF 2.0, there is a noSelectionOption attribute for marking an item that is included for navigational purposes, such as "Select a condiment". This attribute is used in conjunction with validation. If an entry is required and the user selects the "no selection option", a validation error occurs.
You can use f:selectItem's value attribute to access SelectItem instances created in a bean:
<f:selectItem value="#{form.cheeseItem}"/>
The value expression for the value attribute points to a method that returns a javax.faces.model.SelectItem instance:
public SelectItem getCheeseItem() { return new SelectItem("Cheese"); }
javax.faces.model.SelectItem
-
SelectItem(Object value)
Creates a SelectItem with a value. The item label is obtained by applying toString() to the value.
-
SelectItem(Object value, String label)
Creates a SelectItem with a value and a label.
-
SelectItem(Object value, String label, String description)
Creates a SelectItem with a value, label, and description.
-
SelectItem(Object value, String label, String description, boolean disabled)
Creates a SelectItem with a value, label, description, and disabled state.
-
SelectItem(Object value, String label, String description, boolean disabled, boolean noSelectionOption)
Creates a SelectItem with a value, label, description, disabled state, and "no selection option" flag.
The f:selectItems Tag
As we saw in "The f:selectItem Tag" on page 153, f:selectItem is versatile, but it is tedious for specifying more than a few items. The first code fragment shown in that section can be reduced to the following with f:selectItems:
<h:selectOneRadio value="#{form.condiments}> <f:selectItems value="#{form.condimentItems}"/> </h:selectOneRadio>
The value expression #{form.condimentItems} could point to an array of SelectItem instances:
private static SelectItem[] condimentItems = { new SelectItem(1, "Cheese"), new SelectItem(2, "Pickle"), new SelectItem(3, "Mustard"), new SelectItem(4, "Lettuce"), new SelectItem(5, "Onions") }; public SelectItem[] getCondimentItems() { return condimentItems; }
The f:selectItems value attribute must be a value expression that points to one of the following:
- A single SelectItem instance
- A collection
- An array
- A map whose entries represent labels and values
The first option is not very useful. We discuss the other options in the following sections.
Table 4–26 summarizes the attributes of the f:selectItems tag.
Table 4–26. Attributes for f:selectItems
Attribute |
Description |
binding, id |
Basic attributes a |
value |
Value expression that points to a SelectItem instance, an array or collection, or a map |
var |
The name of a variable, used in the value expressions below when traversing an array or collection of objects other than SelectItem |
itemLabel |
Value expression yielding the text shown by the item referenced by the var variable |
itemValue |
Value expression yielding the value of the item referenced by the var variable |
itemDescription |
Value expression yielding the description of the item referenced by the var variable; the description is intended for use by tools |
itemDisabled |
Value expression yielding the disabled HTML attribute of the item referenced by the var variable |
itemLabelEscaped |
Value expression yielding true if special characters in the item's value should be converted to character entities (default), false if the value should be emitted without change |
noSelectionOption |
Value expression that yields the "no selection option" item or string that equals the value of the "no selection option" item |
Using Collections and Arrays with f:selectItems
Before JSF 2.0, collections and arrays had to contain SelectItem instances. That was unfortunate because it coupled your business logic to the JSF API. As of JSF 2.0, the value of f:selectItems can be a collection or array containing objects of any type.
If they are instances of SelectItem, no further processing is done. Otherwise, the labels are obtained by calling toString on each object.
Alternatively, you cau use the var attribute to define a variable that iterates over the array or collection. Then you supply value expressions for the label and value in the attributes itemLabel and itemValue.
For example, suppose you want users to select objects of the following class:
public class Weekday { public String getDayName() { ... } // name in current locale, such as "Monday" public int getDayNumber() { ... } // number such as Calendar.MONDAY (2) ... }
Use the following tag:
<f:selectItems value="#{form.daysOfTheWeek}" var="w" itemLabel="#{w.dayName}" itemValue="#{w.dayNumber}" />
Here, #{form.daysOfTheWeek} yields an array or collection of Weekday objects. The variable w is set to each of the elements. Then a SelectItem object is constructed with the results of the itemLabel and itemValue expressions.
Using Maps with f:selectItems
If the value attribute of the f:selectItems tag yields a map, the JSF implementation creates a SelectItem instance for every entry in the map. The entry's key is used as the item's label, and the entry's value is used as the item's value. For example, here are condiments specified with a map:
private static Map<String, Object> condimentItems; static { condimentItems = new LinkedHashMap<String, Object>(); condimentItems.put("Cheese", 1); // label, value condimentItems.put("Pickle", 2); condimentItems.put("Mustard", 3); condimentItems.put("Lettuce", 4); condimentItems.put("Onions", 5); } public Map<String, Object> getCondimentItems() { return condimentItems; }
Note that you cannot specify item descriptions or disabled status when you use a map.
Pay attention to these two issues when using a map:
- You will generally want to use a LinkedHashMap, not a TreeMap or HashMap. In a LinkedHashMap, you can control the order of the items because items are visited in the order in which they were inserted. If you use a TreeMap, the labels that are presented to the user (which are the keys of the map) are sorted alphabetically. That may or may not be what you want. For example, days of the week would be neatly arranged as Friday Monday Saturday Sunday Thursday Tuesday Wednesday. If you use a HashMap, the items are ordered randomly.
- Map keys are turned into item labels and map values into item values. When a user selects an item, your backing bean receives a value in your map, not a key. For example, in the example above, if the backing bean receives a value of 5, you would need to iterate through the entries if you wanted to find the matching "Onions". Since the value is probably more meaningful to your application than the label, this is usually not a problem, just something to be aware of.
Item Groups
You can group menu or listbox items together, like this:
Here are the JSF tags that define the listbox:
<h:selectManyListbox> <f:selectItems value="#{form.menuItems}"/> </h:selectManyListbox>
The menuItems property is a SelectItem array:
public SelectItem[] getMenuItems() { return menuItems; }
The menuItems array is instantiated like this:
private static SelectItem[] menuItems = { burgers, beverages, condiments };
The burgers, beverages, and condiments variables are SelectItemGroup instances that are instantiated like this:
private SelectItemGroup burgers = new SelectItemGroup("Burgers", // value "burgers on the menu", // description false, // disabled burgerItems); // select items private SelectItemGroup beverages = new SelectItemGroup("Beverages", // value "beverages on the menu", // description false, // disabled beverageItems); // select items private SelectItemGroup condiments = new SelectItemGroup("Condiments", // value "condiments on the menu", // description false, // disabled condimentItems); // select items
Notice that we are using SelectItemGroups to populate an array of SelectItems. We can do that because SelectItemGroup extends SelectItem. The groups are created and initialized like this:
private SelectItem[] burgerItems = { new SelectItem("Qwarter pounder"), new SelectItem("Single"), new SelectItem("Veggie"), }; private SelectItem[] beverageItems = { new SelectItem("Coke"), new SelectItem("Pepsi"), new SelectItem("Water"), new SelectItem("Coffee"), new SelectItem("Tea"), }; private SelectItem[] condimentItems = { new SelectItem("cheese"), new SelectItem("pickle"), new SelectItem("mustard"), new SelectItem("lettuce"), new SelectItem("onions"), };
SelectItemGroup instances encode HTML optgroup elements. For example, the preceding code generates the following HTML:
<select name="_id0:_id1" multiple size="16"> <optgroup label="Burgers"> <option value="1" selected>Qwarter pounder</option> <option value="2">Single</option> <option value="3">Veggie</option> </optgroup> <optgroup label="Beverages"> <option value="4" selected>Coke</option> <option value="5">Pepsi</option> <option value="6">Water</option> <option value="7">Coffee</option> <option value="8">Tea</option> </optgroup> <optgroup label="Condiments"> <option value="9">cheese</option> <option value="10">pickle</option> <option value="11">mustard</option> <option value="12">lettuce</option> <option value="13">onions</option> </optgroup> </select>
javax.faces.model.SelectItemGroup
-
SelectItemGroup(String label)
Creates a group with a label but no selection items.
-
SelectItemGroup(String label, String description, boolean disabled, SelectItem[] items)
Creates a group with a label, a description (which is ignored by the JSF Reference Implementation), a boolean that disables all the items when true, and an array of select items used to populate the group.
-
setSelectItems(SelectItem[] items)
Sets a group's array of SelectItems.
Binding the value Attribute
Whether you are using a set of checkboxes, a menu, or a listbox, you will want to keep track of the item or items selected by the user. For that purpose, you use the value attribute of the selectOne and selectMany tags. Consider this example:
<h:selectOneMenu value="#{form.bestDay}"> <f:selectItems value="#{form.weekdays}"/> </h:selectOneRadio>
The value attribute of h:selectOneMenu refers to the value that the user selects. The value attribute of f:selectItems specifies all possible values.
Suppose the radio buttons were specified with an array of SelectItem objects, containing the following:
new SelectItem(1, "Sunday"), // value, label new SelectItem(2, "Monday"), ...
The user sees the labels (Sunday, Monday, ...), but the application uses the values (1, 2, ...).
There is an important but subtle issue about the Java type of the values. In the web page, the values are always strings:
<option value="1">Sunday</option> <option value="2">Monday</option>
When the page is submitted, the server receives the selected string and must convert it to an appropriate type. The JSF implementation knows how to convert to numbers and enumerated types, but for other types you need to define a converter. (We discuss converters in Chapter 7.)
In our example, the #{form.bestDay} value expression should refer to a property of type int or Integer. Listing 4–13 has an example where the value is an enumerated type.
The value Attribute and Multiple Selections
You can keep track of multiple selections with a selectMany tag. These tags have a value attribute that specifies zero or more selected items, using an array or collection.
Consider an h:selectManyListbox that lets a user choose multiple condiments:
<h:selectManyListbox value="#{form.condiments}"> <f:selectItems value="#{form.condimentItems}"/> </h:selectManyListbox>
Here are the condimentItems and condiments properties:
private static SelectItem[] condimentItems = { new SelectItem(1, "Cheese"), new SelectItem(2, "Pickle"), new SelectItem(3, "Mustard"), new SelectItem(4, "Lettuce"), new SelectItem(5, "Onions"), }; public SelectItem[] getCondimentItems() { return condimentItems; } private int[] condiments; public void setCondiments(int[] newValue) { condiments = newValue; } public int[] getCondiments() { return condiments; }
Instead of an int[] array for the condiments property, you could have used an Integer[] array.
The value of a selectMany tag can be a collection instead of an array, but there are two technical issues that you need to keep in mind. Most importantly, the elements cannot be converted because the collection's element type is not known at runtime. (This is an unfortunate aspect of Java generics. At runtime, an ArrayList<Integer> or ArrayList<String> is only a raw ArrayList, and there is no way of determining the element type. In contrast, Integer[] and String[] are distinct types at runtime.) That means, you should use collections only for strings.
The other complexity is more subtle. When the JSF application receives the user choices, it must construct a new instance of the collection, populate it, and pass the collection to the property setter. But suppose the property type is Set<String>. What kind of Set should be constructed?
Before JSF 2.0, this was not clearly specified. JSF 2.0 lays down the following rules:
- If the tag has a collectionType attribute, its value must be a string or a value expression that evaluates to a fully qualified classname, such as java.util.TreeSet. Instantiate that class.
- Otherwise, get the existing value and try cloning and clearing it.
- If that fails (perhaps because the existing value was null or not cloneable), look at the type of the value expression. If that type is SortedSet, Set, or Queue, construct a TreeSet, HashSet, or LinkedList.
- Otherwise, construct an ArrayList.
For example, suppose you define a languages property:
private Set<String> languages; // initialized with null public Set<String> getLanguages() { return languages; } public void setLanguages(Set<String> newValue) { languages = newValue; }
When the form is submitted for the first time, the property setter is called with a HashSet that contains the user choices (step 3). In subsequent invocations, that set is cloned (step 2). However, suppose you initialize the set:
private Set<String> languages = new TreeSet();
Then a clone of that TreeSet is always returned.
All Together: Checkboxes, Radio Buttons, Menus, and Listboxes
We close out our section on selection tags with an example that exercises nearly all those tags. That example, shown in Figure 4–7, implements a form requesting personal information. We use an h:selectBooleanCheckbox to determine whether the user wants to be contacted, and h:selectOneMenu lets the user select the best day of the week for us to do so.
Figure 4–7 Using checkboxes, radio buttons, menus, and listboxes
The year listbox is implemented with h:selectOneMenu, and it demonstrates the use of a "no selection" item. The language checkboxes are implemented with h:selectManyCheckbox; the education level is implemented with h:selectOneRadio.
Note that the languages are collected in a Set<String>. Also note the styles in the color selector. The disabled Orange option is colored gray, and the selected colors are marked in bold. We use the attribute onchange="submit()" in order to update the styles immediately upon selection.
When the user submits the form, JSF navigation takes us to a JSF page that shows the data the user entered.
The directory structure for the application shown in Figure 4–7 is shown in Figure 4–8. The JSF pages, RegisterForm bean, faces configuration file, and resource bundle are shown in Listings 4–12 through 4–16.
Figure 4–8 The directory structure of the selection example
Listing 4–12. select/web/index.xhtml
1.<?xml version="1.0" encoding="UTF-8"?> 2.<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" 3."http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> 4.<html xmlns="http://www.w3.org/1999/xhtml" 5. xmlns:f="http://java.sun.com/jsf/core" xmlns:h="http://java.sun.com/jsf/html"> 6. <h:head> 7. <h:outputStylesheet library="css" name="styles.css"/> 8. <title>#{msgs.indexWindowTitle}</title> 9. </h:head> 10. 11. <h:body> 12. <h:outputText value="#{msgs.indexPageTitle}" styleClass="emphasis"/> 13. <h:form> 14. <h:panelGrid columns="2"> 15. #{msgs.namePrompt} 16. <h:inputText value="#{form.name}"/> 17. #{msgs.contactMePrompt} 18. <h:selectBooleanCheckbox value="#{form.contactMe}"/> 19. #{msgs.bestDayPrompt} 20. <h:selectManyMenu value="#{form.bestDaysToContact}"> 21. <f:selectItems value="#{form.daysOfTheWeek}" var="w" 22. itemLabel="#{w.dayName}" itemValue="#{w.dayNumber}"/> 23. </h:selectManyMenu> 24. #{msgs.yearOfBirthPrompt} 25. <h:selectOneMenu value="#{form.yearOfBirth}" required="true"> 26. <f:selectItems value="#{form.yearItems}"/> 27. </h:selectOneMenu> 28. #{msgs.colorPrompt} 29. <h:selectManyCheckbox value="#{form.colors}" 30. selectedClass="selected" disabledClass="disabled" 31. onchange="submit()"> 32. <f:selectItems value="#{form.colorItems}"/> 33. </h:selectManyCheckbox> 34. #{msgs.languagePrompt} 35. <h:selectManyListbox size="5" value="#{form.languages}"> 36. <f:selectItems value="#{form.languageItems}"/> 37. </h:selectManyListbox> 38. #{msgs.educationPrompt} 39. <h:selectOneRadio value="#{form.education}" 40. selectedClass="selected" layout="pageDirection"> 41. <f:selectItems value="#{form.educationItems}"/> 42. </h:selectOneRadio> 43. </h:panelGrid> 44. <h:commandButton value="#{msgs.buttonPrompt}" action="showInformation"/> 45. </h:form> 46. <h:messages/> 47. </h:body> 48.</html>
Listing 4–13. select/web/showInformation.xhtml
1.<?xml version="1.0" encoding="UTF-8"?> 2.<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" 3."http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> 4.<html xmlns="http://www.w3.org/1999/xhtml" 5. xmlns:f="http://java.sun.com/jsf/core" xmlns:h="http://java.sun.com/jsf/html"> 6. <h:head> 7. <title>#{msgs.indexWindowTitle}</title> 8. </h:head> 9. <h:body> 10. <h:form> 11. <h:outputStylesheet library="css" name="styles.css" target="head"/> 12. <h:outputFormat value="#{msgs.thankYouLabel}"> 13. <f:param value="#{form.name}"/> 14. </h:outputFormat> 15. <h:panelGrid columns="2"> 16. #{msgs.contactMeLabel} 17. <h:outputText value="#{form.contactMe}"/> 18. #{msgs.bestDayLabel} 19. <h:outputText value="#{form.bestDaysConcatenated}"/> 20. #{msgs.yearOfBirthLabel} 21. <h:outputText value="#{form.yearOfBirth}"/> 22. #{msgs.languageLabel} 23. <h:outputText value="#{form.languages}"/> 24. #{msgs.colorLabel} 25. <h:outputText value="#{form.colorsConcatenated}"/> 26. #{msgs.educationLabel} 27. <h:outputText value="#{form.education}"/> 28. </h:panelGrid> 29. <h:commandButton value="#{msgs.backPrompt}" action="index"/> 30. </h:form> 31. </h:body> 32.</html>
Listing 4–14. select/src/java/com/corejsf/RegisterForm.java
1. package com.corejsf; 2. 3. import java.awt.Color; 4. import java.io.Serializable; 5. import java.text.DateFormatSymbols; 6. import java.util.ArrayList; 7. import java.util.Arrays; 8. import java.util.Calendar; 9. import java.util.Collection; 10. import java.util.LinkedHashMap; 11. import java.util.Map; 12. import java.util.Set; 13. import java.util.TreeSet; 14. 15. import javax.inject.Named; 16. // or import javax.faces.bean.ManagedBean; 17. import javax.enterprise.context.SessionScoped; 18. // or import javax.faces.bean.SessionScoped; 19. import javax.faces.model.SelectItem; 20. 21. @Named("form") // or @ManagedBean(name="form") 22. @SessionScoped 23. public class RegisterForm implements Serializable { 24. public enum Education { HIGH_SCHOOL, BACHELOR, MASTER, DOCTOR }; 25. 26. public static class Weekday { 27. private int dayOfWeek; 28. public Weekday(int dayOfWeek) { 29. this.dayOfWeek = dayOfWeek; 30. } 31. 32. public String getDayName() { 33. DateFormatSymbols symbols = new DateFormatSymbols(); 34. String[] weekdays = symbols.getWeekdays(); 35. return weekdays[dayOfWeek]; 36. } 37. 38. public int getDayNumber() { 39. return dayOfWeek; 40. } 41. } 42. 43. private String name; 44. private boolean contactMe; 45. private int[] bestDaysToContact; 46. private Integer yearOfBirth; 47. private int[] colors; 48. private Set<String> languages = new TreeSet<String>(); 49. private Education education = Education.BACHELOR; 50. 51. public String getName() { return name; } 52. public void setName(String newValue) { name = newValue; } 53. 54. public boolean getContactMe() { return contactMe; } 55. public void setContactMe(boolean newValue) { contactMe = newValue; } 56. 57. public int[] getBestDaysToContact() { return bestDaysToContact; } 58. public void setBestDaysToContact(int[] newValue) { bestDaysToContact = newValue; } 59. 60. public Integer getYearOfBirth() { return yearOfBirth; } 61. public void setYearOfBirth(Integer newValue) { yearOfBirth = newValue; } 62. 63. public int[] getColors() { return colors; } 64. public void setColors(int[] newValue) { colors = newValue; } 65. 66. public Set<String> getLanguages() { return languages; } 67. public void setLanguages(Set<String> newValue) { languages = newValue; } 68. 69. public Education getEducation() { return education; } 70. public void setEducation(Education newValue) { education = newValue; } 71. 72. public Collection<SelectItem> getYearItems() { return birthYears; } 73. 74. public Weekday[] getDaysOfTheWeek() { return daysOfTheWeek; } 75. 76. public SelectItem[] getLanguageItems() { return languageItems; } 77. 78. public SelectItem[] getColorItems() { return colorItems; } 79. 80. public Map<String, Education> getEducationItems() { return educationItems; } 81. 82. public String getBestDaysConcatenated() { 83. return Arrays.toString(bestDaysToContact); 84. } 85. 86. public String getColorsConcatenated() { 87. StringBuilder result = new StringBuilder(); 88. for (int color : colors) result.append(String.format("%06x ", color)); 89. return result.toString(); 90. } 91. 92. private SelectItem[] colorItems = { 93. new SelectItem(Color.RED.getRGB(), "Red"), // value, label 94. new SelectItem(Color.GREEN.getRGB(), "Green"), 95. new SelectItem(Color.BLUE.getRGB(), "Blue"), 96. new SelectItem(Color.YELLOW.getRGB(), "Yellow"), 97. new SelectItem(Color.ORANGE.getRGB(), "Orange", "", true) // disabled 98. }; 99. 100. private static Map<String, Education> educationItems; 101. static { 102. educationItems = new LinkedHashMap<String, Education>(); 103. educationItems.put("High School", Education.HIGH_SCHOOL); // label, value 104. educationItems.put("Bachelor's", Education.BACHELOR); 105. educationItems.put("Master's", Education.MASTER); 106. educationItems.put("Doctorate", Education.DOCTOR); 107. }; 108. 109. private static SelectItem[] languageItems = { 110. new SelectItem("English"), 111. new SelectItem("French"), 112. new SelectItem("Russian"), 113. new SelectItem("Italian"), 114. new SelectItem("Esperanto", "Esperanto", "", true) // disabled 115. }; 116. 117. private static Collection<SelectItem> birthYears; 118. static { 119. birthYears = new ArrayList<SelectItem>(); 120. // The first item is a "no selection" item 121. birthYears.add(new SelectItem(null, "Pick a year:", "", false, false, true)); 122. for (int i = 1900; i < 2020; ++i) birthYears.add(new SelectItem(i)); 123. } 124. 125. private static Weekday[] daysOfTheWeek; 126. static { 127. daysOfTheWeek = new Weekday[7]; 128. for (int i = Calendar.SUNDAY; i <= Calendar.SATURDAY; i++) { 129. daysOfTheWeek[i - Calendar.SUNDAY] = new Weekday(i); 130. } 131. } 132.}
Listing 4–15. select/src/java/com/corejsf/messages.properties
1.indexWindowTitle=Checkboxes, Radio buttons, Menus, and Listboxes 2.indexPageTitle=Please fill out the following information 3. 4.namePrompt=Name: 5.contactMePrompt=Contact me 6.bestDayPrompt=What's the best day to contact you? 7.yearOfBirthPrompt=What year were you born? 8.buttonPrompt=Submit information 9.backPrompt=Back 10.languagePrompt=Select the languages you speak: 11.educationPrompt=Select your highest education level: 12.emailAppPrompt=Select your email application: 13.colorPrompt=Select your favorite colors: 14. 15.thankYouLabel=Thank you {0}, for your information 16.contactMeLabel=Contact me: 17.bestDayLabel=Best day to contact you: 18.yearOfBirthLabel=Your year of birth: 19.colorLabel=Colors: 20.languageLabel=Languages: 21.educationLabel=Education:
Listing 4–16. select/web/resources/css/styles.css
1. .emphasis { 2. font-style: italic; 3. font-size: 1.3em; 4. } 5. .disabled { 6. color: gray; 7. } 8. .selected { 9. font-weight: bold; 10. }