JSF条件包含,因为已在视图中找到组件ID

JSF条件包含,因为已在视图中找到组件ID,jsf,jsf-2,conditional,uiinclude,rendered-attribute,Jsf,Jsf 2,Conditional,Uiinclude,Rendered Attribute,我知道我们不能重复同一视图树中任何组件的ID 我有一个页面,在某些条件下包括其他页面,例如… <h:panelGroup rendered="#{bean.insertMode == 'SINGLE'}"> <ui:include src="_single.xhtml" /> </h:panelGroup> <h:panelGroup rendered="#{bean.insertMode == 'DOUBLE'}"> <ui:

我知道我们不能重复同一视图树中任何组件的ID

我有一个页面,在某些条件下包括其他页面,例如…

<h:panelGroup rendered="#{bean.insertMode == 'SINGLE'}">
   <ui:include src="_single.xhtml" />
</h:panelGroup> 
<h:panelGroup rendered="#{bean.insertMode == 'DOUBLE'}">
   <ui:include src="_double.xhtml" />
</h:panelGroup>

现在在这些页面中,我有了“几乎”相同的组件层次结构(复杂),具有不同的动作行为(不仅是方法调用,还有视图),例如:

_single.xhtml


_double.xhtml


我的小例子效果很好,并且呈现出它应该呈现的效果,但是我得到了

java.lang.IllegalStateException:已在视图中找到组件ID字段ID。

我知道JSF会处理整个页面,即使它们没有包含在内,这就是为什么我会遇到这个异常


在不更改include页面内组件的ID的情况下解决此问题的任何智能方法(尽管它可以工作,但异常很烦人,似乎有问题)

我不想用不同ID的容器组件来包装每一个页面,这样它们就会有一个不同的完整ID,比如formId:fieldID,因为母版页也在这些包含中引用这些组件

发生重复组件ID错误,因为这两个包含在JSF组件树中结束。
并没有阻止它们在JSF组件树中结束,而是阻止它们生成HTML输出

您需要在JSF组件树中有条件地构建它们,而不是有条件地呈现它们的HTML输出。JSTL在这方面非常有用,因为它在视图构建期间运行:


在使用Mojarra的情况下,只需确保至少使用2.1.18或更高版本,否则视图范围的bean的行为将类似于请求范围的bean

另一种方法是在
src
属性中使用EL条件运算符(在视图构建期间,
本身也作为标记处理程序运行):


甚至可以直接使用
insertMode
作为文件名:


无论哪种方式,您都需要绝对确保
{bean.insertMode}
在视图构建期间可用,并且在回发的还原视图阶段可用的值与在初始渲染期间完全相同,否则,视图可能会使用错误的include进行恢复,JSF无法再解码正确的输入和命令。另外,当您想在回发期间更改包含时,确实需要重新生成视图(返回non-
null
/
void
),或者发送重定向

另见:

如果single.xhtml和double.xhtml文件都包含几乎完全相同的结构,为什么不使用一个页面呢?它不是完全相同的结构。。这是完全不同的,它们之间有一些共享字段。。我不想更改这些共享字段的ID:)@Luiggimendozan您可以将它们包装在父页面或子页面中不可见的
NamingContainer
中。使用复合组件制作这样一个不可见的命名容器很容易。@rdcrng请阅读我文章的最后一节:)是的,因此我发表了评论,而不是回答-我知道有更好的方法,我看到BalusC已经指出了:)从2.1.2升级到2.1.18为我保存了它。@Joerg:不用谢。请注意,2.1.x当前已处于2.1.29。
<p:inputText id="fieldID" value="#{bean.value}" />
<p:commandLink actionListener="#{bean.singleAction()}" />
<p:inputText id="fieldID" value="#{bean.value}" />
<p:commandLink actionListener="#{bean.doubleAction()}" />