渲染h:panelGroup在c:forEach中的错误ID

时间:2013-05-23 12:43:39

标签: jsf-2 jboss richfaces jstl

我有一个页面,我在其中渲染一些h:panelGroup面板。这些面板在启动时实现为在插件注册表中注册的插件。 插件api的一部分是一个自定义的jsf组件,我获取扩展点的注册插件,并按路径包含他们的facelet模板:

<c:forEach items="#{pluginRegistry.getPlugins(point)}" var="extension">
    <ui:include src="#{extension.path}" />
</c:forEach>

我包含面板的页面如下:

<h:panelGrid id="dashboard" columns="3">
    <cmf:insertPageFragments point="dashboardExtensionPoint" />
</h:panelGrid>

对于每个面板,都有类似下面的面板模板:

<rich:panel id="caseDetailsPanel" header="panel label">
    <!-- panel content -->
</rich:panel>

现在,问题是pluginsRegistry返回的列表中的第一个面板在提供的id的页面中呈现,例如formId:caseDetailsPanel。其余的都生成了像formId:j_idt223这样的id!显然,如果我想重新渲染一些面板,我就不能这样做。

当环境是jboss AS 7.1和JSF 2.1,richfaces 4.2.3.Final时,会发生这种情况。 当部署在jboss-eap-6.1上时,一切看起来都很好但是现在我不能使用这个jboss版本。

有关如何解决此问题的任何建议?

1 个答案:

答案 0 :(得分:4)

不能有多个具有相同ID的JSF组件。每个JSF组件都必须具有唯一的ID。使用JSTL动态创建JSF组件时,需要手动分配并确保唯一ID,否则JSF将丢弃提供的ID并自动生成唯一ID。

根据具体的功能要求和现有代码,有几种方法可以实现这一目标。

  1. 使用<c:forEach>的迭代索引。

    <c:forEach ... varStatus="loop">
        ...
        <rich:panel id="caseDetailsPanel_#{loop.index}" ...>
    

    这将生成caseDetailsPanel_0caseDetailsPanel_1等,具体取决于当前的迭代索引。

  2. 使用当前迭代项的唯一标识符。基于目前为止提供的信息,如果你有任何信息,目前还不清楚,所以这里只是一个虚构的例子,假设#{extension}后面的类具有代表技术数据库标识符的id属性。

    <c:forEach ... var="extension">
        ...
        <rich:panel id="caseDetailsPanel_#{extension.id}" ...>
    
  3. 如果需要,在具有唯一标识符的<f:subview>中包裹#1或#2,这样您就不需要修改包含。

    <c:forEach ... varStatus="loop">
        <f:subview id="panel_#{loop.index}">
            <ui:include ... />
    

    <f:subview>围绕它创建一个新的NamingContainer,因此您最终获得formId:panel_0:caseDetailsPanelformId:panel_1:caseDetailsPanel等等。

  4. 完全不同的替代方法是使用<ui:repeat>代替<c:forEach><ui:repeat>在视图构建期间不运行,但在视图渲染时间内运行。这样在组件树中物理上只有一个<rich:panel id="caseDetailsPanel">组件,在生成HTML期间多次重复使用,因此JSF将负责使用<ui:repeat>索引生成正确的ID,如formId:repeatId:0:caseDetailsPanel。但是,这反过来可能会导致<ui:include>出现问题,因为它也会在视图构建期间运行,因此无法获得#{extension}

相关问题