JSF2.0 - h:包含下拉列的dataTable - 显示/隐藏每个表行的下拉列表的问题

时间:2011-06-06 22:35:01

标签: jsf-2

我有一个表,其中一个列包含一个下拉列表(HtmlSelectItems组件)。 对于此表中的任何给定行,我希望能够根据特定的应用程序条件在运行时显示或隐藏下拉列表。

我在这种情况下的解决方案是使用JSF2.0实现提供的组件的预渲染事件监听器机制。基本上在JSF页面中,我为HtmlSelectItems组件(生活在h:列中)分配了一个id,并使用pre render f:event元素设置它。 f:event指向我的一个接收组件id并处理它的方法。

我的问题是HtmlSelectItems实例在所有表行之间是SHARED,如果我在一个下拉列表组件上调用HtmlSelectItems.setRender(false),则所有后续行将停止显示下拉列表。实际上,一旦在下拉列表中调用第一个setRender(false),f:事件预呈现侦听器将停止被调用

我可以理解在表行之间共享一个HtmlSelectItems实例的事实 对整体性能有积极影响,但不应该在每一行重新初始化此组件实例吗?

非常感谢你对这方面的任何澄清。

1 个答案:

答案 0 :(得分:1)

您需要让rendered条件依赖于行本身,而不是父bean。

E.g。

<h:dataTable value="#{bean.list}" var="item">
    <h:column>
        <h:selectOneMenu rendered="#{item.showDropdown}">
            ...
        </h:selectOneMenu>
    </h:column>
</h:dataTable>

而不是

<h:dataTable value="#{bean.list}" var="item">
    <h:column>
        <h:selectOneMenu rendered="#{bean.showDropdown}">
            ...
        </h:selectOneMenu>
    </h:column>
</h:dataTable>

或者,如果由于某些设计限制需要由#{bean}而不是#{item}确定,那么有几种方法。

如果您使用DataModel作为数据表的value,那么您可以按如下方式获取当前行:

public boolean isShowDropdown() {
    Item item = model.getRowData();
    return shouldShowDropdown(item); // Do your thing.
}

如果没有,则保持Map<Long, Boolean>,而密钥实际上是行项的标识符,值表示是否应显示下拉列表。然后可以按如下方式使用:

<h:dataTable value="#{bean.list}" var="item">
    <h:column>
        <h:selectOneMenu rendered="#{bean.showDropdown[item.id]}">
            ...
        </h:selectOneMenu>
    </h:column>
</h:dataTable>