在视图中使用复合组件两次在JSF中重复组件ID

时间:2015-10-21 11:36:10

标签: jsf facelets composite-component

我"继承"我公司的JSF 2(JSF 2.2.7)应用程序,面临java.lang.IllegalStateException,因为两个组件似乎具有相同的ID。

视图的结构如下(为了说明目的,我提取了相关代码,它可能包含一些拼写错误/无效语法,因为我更改了一些名称):

<p:commandButton id="editButton"
   action="#{controller.prepareItem()}"
   update=":itemEditDlg" oncomplete="PF('itemtEditDlg').show()" />


<comp:editItemDlg id="itemEditDlg"  />

<p:dialog id="anotherDlg" >
   <h:form id="anotherForm">
      <c:forEach items="#{controller.allArgs}" var="arg" >
         <!-- next line is the problem -->
         <comp:mycomponent arg="#{arg}"  />
      </c:forEach>
   </h:form>
</p:dialog>

mycomponent.xhtml如下所示:

<cc:interface>
    <cc:attribute name="arg" required="true" />
</cc:interface>
<cc:implementation>
    <p:inputText id="argValue" value="#{cc.attrs.arg}" />
    <p:message id="argValueMessage" for="argValue" />
</cc:implementation>

重要提示:mycomponent组件也在editItemDlg中使用(与&#34; anotherDlg&#34;中的方式相同),即在对话框和forEach-loop中使用

如果我点击editButton,我会得到:

java.lang.IllegalArgumentException: Component ID anotherForm:j_idt192:argValue  
has already been found in the view.

它很奇怪,因为&#34; anotherDlg&#34;在这种情况下不是开放的,但显然已经呈现。

我在StackTrace中获得以下信息(仅显示相关部分):

         +id: j_idt192
             type: javax.faces.component.UINamingContainer@399bd0dc
              +id: j_id2
               type: javax.faces.component.UIPanel@24ad3910
                +id: argValue  <===============
                 type: org.primefaces.component.inputtext.InputText@687d5c3f
                +id: argValueMessage
                 type: org.primefaces.component.message.Message@7e3361b0
                +id: argValue  <===============
                 type: org.primefaces.component.inputtext.InputText@5f52aa8a
                +id: argValueMessage
                 type: org.primefaces.component.message.Message@2c3a7aea

所以不知何故,这些组件会被渲染两次,但我无法弄清楚原因。

我已经走过了SO answer,但我无法确定哪些列出的原因是我的问题。我没有使用任何绑定。

到目前为止我尝试过的方法:明确地设置id,即围绕mycomonent,将循环计数器作为ID传递给组件等,但没有成功。我认为问题无法在mycomponent中解决。我找到的唯一解决方法是制作mycomponent的物理副本,并在我的anotherForm中引用该副本(例如editItemDlg和anotherDlg不使用相同的组件)。

感谢任何帮助

2 个答案:

答案 0 :(得分:0)

您不应为组件上的输入文本指定ID。

如果您在表单上循环遍历数组,则可以确定您的输入文本元素将被多次创建。

  

指定的标识符在作为NamingContainer的最近祖先UIComponent的后代的所有组件(包括facet)中必须是唯一的,或者如果没有这样的祖先是NamingContainer,则在整个组件树的范围内。

正如UINamingContainer所述。

让我们考虑一下您的select列表中有两个项目。

您生成的输出:

controller.allArgs

这会导致重复的id异常。

您可以创建一个新的命名容器,以保持<form id="anotherForm"> <input type="text" id="**argValue**"> <p:message> <input type="text" id="**argValue**"> <p:message> </form> 唯一,或在您的添加中附加索引信息。

答案 1 :(得分:0)

你现在拥有的是具有相同ID的多个JSF组件,这些组件无法正常工作..

动态生成组件时,必须向相应的ID附加某种迭代索引。

<p:inputText id="argValue_#{bean.counter}" value="#{cc.attrs.arg}" />
    <p:message id="argValueMessage_#{bean.counter}" for="argValue" />

你可以做的最好的事情是完全删除id标签,让JSF自动生成它们。

当然,如果你没有从其他地方反对那些ids。