Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

JSF-2 f:selectItems with Map does not display itemLabel

Tags:

map

jsf

el

jsf-2

When I use f:selectItems to display items in a Map I cannot display the value of the Map item, only the key. f:selectItems does not use the itemLabel at all. When I use a List instead things work.

The following does make use of the itemLabel to display the "description" of an item in a List:

<h:selectOneMenu>
  <f:selectItems value="#{testBB.testList}" var="s"
    itemLabel="TEST #{s.description}" itemValue="#{TEST s.name}" />
</h:
selectOneMenu>

The following attempt to display the value of an item in a Map does not work. It displays the item's key, but not using the itemLabel attribute, as can be discerned by that lack of output of the "TEST" text.

<rich:select>
  <f:selectItems value="#{testBB.testMap}" var="s"
    itemLabel="TEST #{s.value}" itemValue="TEST #{s.key}" />
</rich:select>

The simple backing bean used follows:

public class TestBB {
  private Map<String, String> testMap;
  private List<TestItem> testList;

  public TestBB() {
    testMap = new HashMap<String, String>();
    testMap.put("1_key", "Item One");
    testMap.put("2_key", "Item Two");
    testMap.put("3_key", "Item Three");

    testList = new ArrayList<TestItem>();
    testList.add( new TestItem("name_1", "description_1") );
    testList.add( new TestItem("name_2", "description_2") );
    testList.add( new TestItem("name_3", "description_3") );
  }

  public Map<String, String> getTestMap() {
    return testMap;
  }

  public List<TestItem> getTestList() {
    return testList;
  }

}

So, any ideas on how to make this work, that is, how to effectively use a Map with selectItems?

like image 664
Alex Ormond Avatar asked May 18 '12 15:05

Alex Ormond


1 Answers

Your question is sound, but the code makes it confusing and ambiguous. I'll just ignore your code in this answer.

As to the concrete question "How to use Map in <f:selectItems>", you need to realize that map keys are by default been used as item labels and that map values are by default been used as item values. You seem to expect it to be the other way round (honestly, I'd intuitively also expect that, but that was just a design desicion --the map key forces uniqueness and option labels should in UI perspective definitely be unique, but option values does not necessarily need to be unique).

So, this should do (note that I use LinkedHashMap here as it maintains the insertion order):

map = new LinkedHashMap<String, String>();
map.put("Label 1", "value1");
map.put("Label 2", "value2");
map.put("Label 3", "value3");

with

<f:selectItems value="#{bean.map}" />

If you want so swap the keys and values, then you should be iterating over Map#entrySet(). This works only when your environment supports EL 2.2 as you have to invoke it by a direct method invocation as there's no getter for that.

E.g.

map = new LinkedHashMap<String, String>();
map.put("value1", "Label 1");
map.put("value2", "Label 2");
map.put("value3", "Label 3");

with

<f:selectItems value="#{bean.map.entrySet()}" var="entry" 
    itemValue="#{entry.key}" itemLabel="#{entry.value}" />

See also:

  • Our selectOneMenu wiki page
like image 195
BalusC Avatar answered Oct 06 '22 01:10

BalusC