17

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?

Alex Ormond
  • 171
  • 1
  • 1
  • 3
  • 1
    Looks fine and should work fine apart from 2 mistakes which do not seem to be related to your concrete problem: 1) `#{TEST s.name}` is invalid EL, but it breaks your `List` menu only. 2) `HashMap` is by nature unordered, you should be using `LinkedHashMap`, but that would cause problems on submits only. Which JSF impl/version exactly are you using? Also, you're using `` instead of `` for the `Map` menu, doesn't that suggest something? – BalusC May 18 '12 at 15:25

1 Answers1

46

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:

Community
  • 1
  • 1
BalusC
  • 1,082,665
  • 372
  • 3,610
  • 3,555
  • @BalusC, doing the first way but can't get to work... Running Jboss AS 7.1 "java.util.LinkedHashMap cannot be cast to javax.faces.model.SelectItem" – jacktrades Jan 17 '13 at 19:49
  • 2
    @jack: that can happen if you're using `` instead of ``. Watch out the plural. – BalusC Jan 17 '13 at 19:53
  • 1
    @jack: specify an enum converter. – BalusC Jan 17 '13 at 20:27
  • Do you mean a custom converter annotated with @FacesConverter, right? The enum is displaying correctly... So Why implement getAsString method? – jacktrades Jan 21 '13 at 21:08
  • @jack: enum converter is only mandatory if you have an `UISelectMany` component which is bound to a `List` property instead of `Enum[]`. See also among others http://stackoverflow.com/questions/3822058/jsf-2-0-use-enum-in-selectmany-menu/ and https://showcase-omnifaces.rhcloud.com/showcase/converters/GenericEnumConverter.xhtml – BalusC Jan 21 '13 at 21:10
  • I get this error loading the webPage: The class 'java.lang.String' does not have the property 'key' – xav56883728 Dec 15 '14 at 10:22
  • I get this error loading the webPage: The class 'java.lang.String' does not have the property 'key'. In my case country is an string but how can I set on my bean – xav56883728 Dec 15 '14 at 10:50
  • Thanks. Confusing side note: I get a warning when I use itemValue="#{entry.key}". It says "key" cannot be resolved. Same for value. How on earth is one supposed to find out that it actually works, despite the warning ? – Tim Jul 28 '16 at 11:50
  • @Tim: the warning is not coming from JSF nor EL, but from the tooling (the IDE and all of its plugins you're using). Use Notepad instead if it annoys you. – BalusC Jul 28 '16 at 12:11
  • Oh ok, thanks. But Eclipse should be able to show this correctly, then. – Tim Jul 28 '16 at 12:18