JSF-2 f:selectItems with Map 不显示 itemLabel

Posted

技术标签:

【中文标题】JSF-2 f:selectItems with Map 不显示 itemLabel【英文标题】:JSF-2 f:selectItems with Map does not display itemLabel 【发布时间】:2012-05-26 04:31:28 【问题描述】:

当我使用 f:selectItems 在 Map 中显示项目时,我无法显示 Map 项目的值,只能显示键。 f:selectItems 根本不使用 itemLabel。当我改用 List 时,一切正常。

以下确实使用 itemLabel 来显示列表中项目的“描述”:

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

以下尝试在地图中显示项目的值不起作用。它显示项目的键,但不使用 itemLabel 属性,这可以通过缺少“TEST”文本的输出来识别。

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

使用的简单支持bean如下:

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;
  


那么,关于如何使这项工作发挥作用的任何想法,即如何有效地使用带有 selectItems 的 Map?

【问题讨论】:

看起来很好,应该可以正常工作,除了 2 个似乎与您的具体问题无关的错误:1) #TEST s.name 是无效的 EL,但它只会破坏您的 List 菜单。 2) HashMap 本质上是无序的,您应该使用LinkedHashMap,但这只会导致提交问题。您到底使用的是哪个 JSF impl/version?另外,您在Map 菜单中使用&lt;rich:select&gt; 而不是&lt;h:selectOneMenu&gt;,这不是有什么建议吗? 【参考方案1】:

您的问题是正确的,但代码使它令人困惑和模棱两可。我将在此答案中忽略您的代码。

至于具体问题“如何在&lt;f:selectItems&gt;中使用Map,您需要意识到默认情况下使用映射键作为项目标签,并且默认使用映射值被用作项目值。您似乎希望它是相反的(老实说,我直觉上也希望如此,但这只是一个设计决定 - 地图键强制唯一性和选项标签在 UI 角度应该绝对是唯一的,但选项值不一定必须是唯一的)。

所以,应该这样做(注意我在这里使用LinkedHashMap,因为它维护了插入顺序):

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

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

如果你想交换键和值,那么你应该迭代Map#entrySet()。这仅在您的环境支持 EL 2.2 时有效,因为您必须通过直接方法调用来调用它,因为没有 getter。

例如

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

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

另见:

Our selectOneMenu wiki page

【讨论】:

@BalusC,采用第一种方式,但无法开始工作... Running Jboss AS 7.1 "java.util.LinkedHashMap cannot be cast to javax.faces.model.SelectItem" @jack:如果您使用&lt;f:selectItem&gt; 而不是&lt;f:selectItems&gt;,就会发生这种情况。注意复数。 @jack: 指定一个枚举转换器。 您的意思是使用@FacesConverter 注释的自定义转换器,对吗?枚举显示正确...那么为什么要实现 getAsString 方法? @jack:枚举转换器仅在您有一个绑定到List&lt;Enum&gt; 属性而不是Enum[]UISelectMany 组件时是必需的。另请参阅 ***.com/questions/3822058/… 和 showcase-omnifaces.rhcloud.com/showcase/converters/…

以上是关于JSF-2 f:selectItems with Map 不显示 itemLabel的主要内容,如果未能解决你的问题,请参考以下文章

JSF-2 f:带有Map的selectItems不显示itemLabel

<f:selectItems> 中的对象作为 itemValue [重复]

<f:selectItems> 未在 <h:selectManyListbox> 中呈现

不断收到 javax.faces.application.ViewExpiredException: viewId with jsf 2 [重复]

何时使用 valueChangeListener 或 f:ajax 监听器?

jsf 1.2和jsf 2.0之间的区别