Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

JSF 2 : selection grouping with SelectItemGroup + POJO

Tags:

jsf

jsf-2

I have tried working with the grouped selections with something like this :

<h:selectOneMenu value="#{selectionLabBean.oneSelectMenuGroup}"
    id="SelectOneMenuGroup" >
        <f:selectItems value="#{selectionLabBean.heroGroupList}" />
</h:selectOneMenu>
<p:message for="SelectOneMenuGroup" />

where the heroGroupList is something like this :

SelectItem[] heroArr = new SelectItem[] {
    new SelectItem("Paladin"),
    ...
};
heroListWithGrouping.add(
    new SelectItemGroup("Human", 
        "A collection of human race Heroes", 
        false,
        heroArr
    )
);
.....

And i'm left wondering if i can do this kind of grouping with POJOs instead of SelectItem objects ?

If i couldnt achieve this, i think i have to somehow convert my domain objects or my query results into arrays of SelectItem to make it work.

Any ideas ?

like image 491
Albert Gan Avatar asked Dec 29 '10 09:12

Albert Gan


2 Answers

That's indeed not possible when you want to use SelectItemGroup. You need to convert from collection of POJO's to List<SelectItem> in a double for-loop during bean's (post)construction.

@PostConstruct
public void init() {
    List<HeroRace> heroRaces = getItSomehowFromDatabase();
    this.heroGroupList = new ArrayList<SelectItem>();
    for (HeroRace heroRace : heroRaces) {
        SelectItemGroup group = new SelectItemGroup(heroRace.getName()); // Human, etc
        List<SelectItem> heroes = new ArrayList<SelectItem>();
        for (Hero hero : heroRace.getHeroes()) {
            heroes.add(new SelectItem(hero.getName()); // Paladin, etc
        }
        group.setSelectItems(heroes.toArray(new SelectItem[heroes.size()]));
        this.heroGroupList.add(group);
    }
}

You could also use Hero as item value

heroes.add(new SelectItem(hero, hero.getName()); // Paladin, etc

so that you can bind #{selectionLabBean.oneSelectMenuGroup} to a Hero type instead of String. But then you need to supply a Converter. That part is already answered by Amorfis.

like image 66
BalusC Avatar answered Nov 14 '22 05:11

BalusC


Yes, you can return List or array of POJOs instead of SelectItems. You'll need converter for this to work, but it's not a big deal. So, converter first:

@FacesConverter(forClass=Hero.class)
public class HeroConverter implements Converter {

  @Override
  public Object getAsObject(FacesContext context, UIComponent component, String value) {
      return new Hero(value);
  }

  @Override
  public String getAsString(FacesContext context, UIComponent component, Object value) {
      return ((Hero)value).getName();
  }
}

Now if you return list of Heroes to <f:selectItems>, you have options in HTML where label is Hero.toString(), and value is returned from HeroConverter.getAsString().

One more thing. If you submit some value for this selection, JSF converts it to object and checks (by equals() method) if this object was in list of objects for selection. So in case above, you'll need to override equals() in Hero to check if names are equal. Another solution is not to create new instance in getAsObject, but to keep somewhere list of available Heroes and return this list to <f:selectionItems> and return object from this list in getAsObject().

like image 22
amorfis Avatar answered Nov 14 '22 06:11

amorfis