ui:repeat 不适用于地图

Posted

技术标签:

【中文标题】ui:repeat 不适用于地图【英文标题】:ui:repeat doesn't work with Map 【发布时间】:2012-01-23 01:55:08 【问题描述】:

我有一个 Map 的键/值,我在 @PostConstruct 中初始化如下:

Map<String, String> myMap;

@PostConstruct
public void init() 

  myMap=new LinkedHashMap<String, String>();
  myMap.put("myKey","myValue");



public Map<String, String> getMyMap() 
    return myMap;


public void setMyMap(Map<String, String> myMap) 
    this.myMap = myMap;

当我尝试使用&lt;ui:repeat&gt; 迭代此 Map 时,如下所示,并在 Map 的 getter 上设置了一个断点,我注意到它没有被调用,因此没有打印任何内容:

<ice:panelGroup>
    <ui:repeat items="#myBean.myMap" var="entry" varStatus="loop">
        <input type="checkbox" name="myCheckBoxes" value="#entry.value" />
        <span class="#fn:contains(entry.value,'g') ? 'bold-style' : ''">#entry.key</span>
    </ui:repeat>
</ice:panelGroup>

但是当用&lt;c:foreach&gt; 替换上面的代码时,一切正常,并且列表按预期打印,任何想法为什么我会出现这种行为?

【问题讨论】:

【参考方案1】:

更新: JSF 2.3(自 2017 年起)支持此 out of the box。

很遗憾,UIDataUIRepeat 不支持在 JSF 中迭代地图。

如果这让您感到困扰(我想确实如此),请为以下问题投票,并在可能的情况下发表评论,说明您对此的感受:

http://java.net/jira/browse/JAVASERVERFACES_SPEC_PUBLIC-479

同时,您可以使用一些小帮助代码来迭代 Map:

/**
 * Converts a Map to a List filled with its entries. This is needed since 
 * very few if any JSF iteration components are able to iterate over a map.
 */
public static <T, S> List<Map.Entry<T, S>> mapToList(Map<T, S> map) 

    if (map == null) 
        return null;
    

    List<Map.Entry<T, S>> list = new ArrayList<Map.Entry<T, S>>();
    list.addAll(map.entrySet());

    return list;

然后在 *-taglib.xml 文件中定义一个 EL 函数,如下所示:

<namespace>http://example.com/util</namespace> 

<function>
    <function-name>mapToList</function-name>
    <function-class>com.example.SomeClass</function-class>
    <function-signature>java.util.List mapToList(java.util.Map)</function-signature>
</function>

最后像这样在 Facelet 上使用它:

<html xmlns:util="http://example.com/util">

    <ui:repeat value="#util:mapToList(someDate)" var="entry" >
        Key = #entry.key Value = #entry.value <br/>
    </ui:repeat>

【讨论】:

@Arjan Tijms,感谢您的出色回答,顺便说一句,我该如何为这个问题投票? 创建一个帐户并登录(快速简便),然后在页面左侧,“操作”下方的链接列表中间某处有一个“投票”链接。 请提供有关创建新标签库文件的更多信息。 @Msaleh 我认为最好创建一个关于如何创建 EL 函数的新问题。在 SO 上,将问题尽可能集中在一个主题上是常态。 嗨@ArjanTijms,我认为提一下这在JSF 2 的早期阶段是不可能实现的可能是个好主意,但现在它实际上是可能的。只为新手。【参考方案2】:

似乎在 JSF 1.2 上对我有用,希望对某人有所帮助...

    <h:panelGroup>
      <ul>
        <ui:repeat value="#myBean.myMap.keySet().toArray()" var="key">
          <li>key:#key</li>
          <li>value:#myBean.myMap[key]</li>
        </ui:repeat>
      </ul>
    </h:panelGroup>

【讨论】:

适用于#sessionScope 地图。 这个答案可能没有多少赞成票,但它是迄今为止我最喜欢的,也是最终让我工作的答案【参考方案3】:
<a4j:repeat value="#myBean.myMap.entrySet().toArray()" var="_entry">
        <h:outputText value="#_entry.key"/><br/>
        <h:outputText value="#_entry.value"/>
</a4j:repeat>

也可以与&lt;ui:repeat&gt;一起使用

【讨论】:

像魅力一样工作。 Primefaces 6.x JSF 2.2 和 p:repeat 谢谢。 这确实有效,但 IDE 抱怨 _entry.key 和 _entry.value 无法解析。有人知道如何解决这个问题吗?【参考方案4】:

有了 el 2.2 支持,您可以像下面那样迭代地图。

<ui:repeat value="#myBean.stats.keySet().toArray()" var="x">
    <h:outputText value="#myBean.stats.get(x)" /><br />
</ui:repeat>

【讨论】:

这是非常低效的,因为在每个get(x) 期间都会再次进行完整的地图查找。更好地迭代entrySet()

以上是关于ui:repeat 不适用于地图的主要内容,如果未能解决你的问题,请参考以下文章

有条件地渲染 tr,使用 ui:repeat 构建表

ui:repeat 中条件渲染子类的 PropertyNotFoundException

使用 ui:repeat 访问本机查询列表

c:forEach vs ui:repeat(又名 ice:panelSeries)

使用 JSF ui:repeat 循环执行带状态的逻辑

如何为 h:dataTable/ui:repeat 的每一行/项目设置转换器属性?