jsfjakarta-eejsf-2jboss-weld

JSF 2.0: use Enum values for selectOneMenu


I'm using JSF 2.0 and want to fill a selectOneMenu with the values of my Enum. A simple example:

// Sample Enum
public enum Gender {
  MALE("Male"),
  FEMALE("Female");

  private final String label;

  private Gender(String label) {
    this.label = label;
  }

  public String getLabel() {
    return this.label;
  }
}

Unfortunately, i can't use Seam for my current project, which had a nice <s:convertEnum/> Tag that did most of the work. In Seam, to use the values of the Enum, i had to write the following markup (and create a factory that provides the #{genderValues}:

<!-- the Seam way -->
<h:selectOneMenu id="persongender" value="#{person.gender}">
  <s:selectItems var="_gender" value="#{genderValues}"" label="#{_gender.label}"/>
  <s:convertEnum/>
</h:selectOneMenu>

The result is that i don't have to declare the Enum values explicitely anymore inside the markup. I know that this is not very easy in JSF <2.0, but is there any new in JSF2 to help with this issue? Or does Weld help here somehow? If there is nothing new in JSF2, what's the easiest way to do it in JSF 1.2?

Or can i even integrate the Seam JSF tag and the corresponding classes of Seam to get the same feature in a JavaEE6-App (without the Seam container)?


Solution

  • Ok, here is the final way: - Register the standard enum converter in faces-config.xml (optional):

    <converter>
      <converter-for-class>java.lang.Enum</converter-for-class>
      <converter-class>javax.faces.convert.EnumConverter</converter-class>
    </converter>
    

    Add a function for example to a managed bean which converts the Enum values to an array of SelectItems:

    @ManagedBean
    public class GenderBean {
      public SelectItem[] getGenderValues() {
        SelectItem[] items = new SelectItem[Gender.values().length];
        int i = 0;
        for(Gender g: Gender.values()) {
          items[i++] = new SelectItem(g, g.getLabel());
        }
        return items;
      }
    }
    

    Then bind this function to the selectOneMenu in JSF:

    <h:selectOneMenu id="gender" value="#{person.gender}">
      <!-- use property name not method name -->
      <f:selectItems value="#{genderBean.genderValues}" />
    </h:selectOneMenu>
    

    That's it! Not the first explanation for this problem on the net. But i think it's the easiest & shortest one ;)