根据 hashmap 列表动态生成 h:column

Posted

技术标签:

【中文标题】根据 hashmap 列表动态生成 h:column【英文标题】:Dynamically generate h:column based on list of hashmaps 【发布时间】:2012-10-22 00:38:22 【问题描述】:

在我的应用程序中,我想显示一个带有托管 bean 属性的 <h:dataTable>。目前,此表是从 List<Folder> 创建的。现在我想将Folder 更改为更动态的东西。那是因为如果我决定稍后添加另一个字段,我不想更改 Folder 类。我只需要在Map<String, Object> 中添加另一个条目,而不是在Folder 中引入一个新字段。

那么,是否可以将List<Map<String, Object>> 绑定到<h:dataTable>

【问题讨论】:

【参考方案1】:

是否可以将 HashMaps 列表绑定到 jsf 组件 h:dataTable?

只有在生成必要的<h:column> 标记和视图构建时间标记(例如 JSTL <c:forEach>)时才有可能。

这是一个具体的启动示例,假设您的环境支持 EL 2.2:

<h:dataTable value="#bean.listOfMaps" var="map">
    <c:forEach items="#bean.listOfMaps[0].keySet().toArray()" var="key">
        <h:column>
            #map[key]
        </h:column> 
    </c:forEach>
</h:dataTable>

(如果您的环境不支持 EL 2.2,您需要提供另一个 getter,它将映射键集返回为 String[]List&lt;String&gt;;还要记住 HashMap本质上是无序的,您可能希望使用LinkedHashMap 来维护插入顺序)

当您使用早于 2.1.18 的 Mojarra 版本时,缺点是 #bean 必须是请求范围(而不是视图范围)。或者至少,&lt;c:forEach items&gt; 应该引用一个请求范围的 bean。否则,当视图范围尚不可用时,&lt;c:forEach&gt; 在视图构建期间运行时,将在每个 HTTP 请求上重新创建视图范围 bean。如果您绝对需要 &lt;h:dataTable&gt; 的视图范围 bean,那么您始终可以专门为 &lt;c:forEach items&gt; 创建一个单独的请求范围 bean。解决方案是升级到 Mojarra 2.1.18 或更高版本。有关一些背景信息,另请参阅JSTL in JSF2 Facelets... makes sense?

诸如PrimeFaces 之类的JSF 组件库可能会提供一个&lt;x:columns&gt; 标记,这使得这更容易,例如&lt;p:dataTable&gt; with &lt;p:columns&gt;

<p:dataTable value="#bean.listOfMaps" var="map">
    <p:columns value="#bean.listOfMaps[0].keySet().toArray()" var="key">
        #map[key]
    </p:columns>
</p:dataTable>

【讨论】:

啊,这就是我想要的。唯一烦人的是我必须使用 forEach。我在某处读到,还可以为您自己的数据结构实现一些接口(不记得名称),以便 jsf 知道如何呈现它。这是可能的还是我在那里搞错了? 我认为你弄错了 :) 对于&lt;h:dataTable&gt;UIColumn 子级确实必须在视图构建期间填充。 &lt;c:forEach&gt; 是在视图构建期间运行的唯一可用迭代标记。

以上是关于根据 hashmap 列表动态生成 h:column的主要内容,如果未能解决你的问题,请参考以下文章

Cglib根据数据库表数据动态生成对象

js动态生成数据列表

js动态生成数据列表

JQuery 动态加载 HTML 元素时绑定点击事件无效问题

动态生成表单

动态保存绘图列表