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



我在我的公司"继承"了一个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组件也在edittitemdlg中使用(与"anotherDlg"的方式相同),即在对话框和forEach-loop中使用)

如果我点击editButton,我得到:

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

这很奇怪,因为"anotherDlg"在这种情况下不是打开的,但显然已经渲染了。

我在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个答案,但我不能确定列出的原因中哪一个是我的问题。我不使用任何绑定。

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

感谢您的帮助

你不应该为你的组件上的输入文本指定一个id。

如果循环遍历表单上的数组,可以肯定的是输入文本元素将被创建不止一次。

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

UINamingContainer.

让我们考虑你的controller.allArgs在清单上有两个项目。

生成的输出:

<form id="anotherForm">
   <input type="text" id="**argValue**">
   <p:message>
   <input type="text" id="**argValue**">
   <p:message>
</form>

这将导致一个重复的id异常。

您可以创建一个新的命名容器来保持您的input id的唯一性,或者在您的add上附加索引信息。

您现在拥有的是具有相同ID的多个JSF组件,这将无法工作。

动态生成组件时,必须在各自的id后面附加某种迭代索引。

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

您能做的最好的事情是完全删除id标记,让JSF自动生成它们。

当然,如果你不从其他地方引用这些id

最新更新