0

I'm struggling on this problem because it destroys my modularity a bit. I'm using JSF 1.2 and facing to use an h:selectOneMenu to select one value of a given set of Enums.

e.g.

public enum State {    
        A,B,C;
};

For instance, i'd do sth. like this:

<h:selectOneMenu>
      <f:selectItem itemValue="A" itemLabel="text" />
      <f:selectItem itemValue="B" itemLabel="text" />
      <f:selectItem itemValue="C" itemLabel="text" />
</h:selectOneMenu>

So i'm searching for a way (e.g. a custom tag) to get this more generic.

Regarding the view component I want to get all available choices as an independent f:selectItem in my menu.

The available choices could be passed by a list or sth. else.

The first method I tried was to use an a4j:repeat tag for my selectItems with a set of choices passed to this tag, but the only thing I got was an empty menu.

My idea was some kind of custom tag that looks like this:

<namespace:enumMenu enumValues="#{values}" value=#{value}" />

Consider a passed set of enums with values A,B,C,D it should result in sth. like

    <h:selectOneMenu value=#{value}>
          <!-- REPEAT for every enum Item in the passed #values -->
          <f:selectItem itemValue="A" />
          <f:selectItem itemValue="B" />
          <f:selectItem itemValue="C" />
          <f:selectItem itemValue="D" />
    </h:selectOneMenu>

Every help is appreciated

DmiN
  • 736
  • 1
  • 7
  • 21

1 Answers1

3

The <a4j:repeat> failed because the <f:xxx> components must be available during view build time in order to be inserted in component tree, but the <a4j:repeat> runs during view render time. You need JSTL <c:forEach> instead.

<h:selectOneMenu ...>
    <c:forEach ...>
        <f:selectItem />
    </c:forEach>
</h:selectOneMenu>

See also:


An alternative is to just use <f:selectItems>. JSF 1.2 has a builtin enum converter, so all you need is this:

private State selectedState; // +getter+setter
private SelectItem[] availableStateItems; // +getter (no setter necessary!)

@PostConstruct
public void init() {
    State[] availableStates = State.values();
    availableStateItems = new SelectItem[availableStates.length];

    for (int i = 0; i < availableStates.length; i++) {
        availableStateItems[i] = new SelectItem(availableStates[i]);
    }
}

with

<h:selectOneMenu value="#{bean.selectedState}">
    <f:selectItems value="#{bean.availableStateItems}" />
</h:selectOneMenu>

You can even put availableStateItems in a completely separate application scoped managed bean, so that the list of available items is initialized only once during application's lifetime.

Please note that the above answer is JSF 1.2 targeted, since JSF 2.x you do not need to convert it to SelectItem[] anymore, just State[] as obtained by State.values() has been sufficient.

See also:

Community
  • 1
  • 1
BalusC
  • 1,082,665
  • 372
  • 3,610
  • 3,555
  • actually you're right, thanks. It is kind of strange that i didn't find sth. that cover this topic over google, but here everything is answered. I think i should rethink my searching strategy :) – DmiN May 20 '13 at 18:07