Duplicate component ID in JSF using composite component twice in view

最后都变了- 提交于 2020-01-02 05:11:49

问题


I "inherited" a JSF 2 (JSF 2.2.7) application in my company and facing a java.lang.IllegalStateException because two component seem to have the same ID.

The structure of the view is as follows (I extracted the relevant code for illustration purpose, it may contain some typos/invalid syntax as I changed some names):

<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 looks as follows:

<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>

Important: The mycomponent component is also used inside editItemDlg (in the same manner as in "anotherDlg"), i.e. within an dialog and forEach-loop)

If I click the editButton, I get:

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

Its rather strange because the "anotherDlg" is not openend in this case, but apparently already rendered.

I get the following info in the StackTrace (only relevant parts shown):

         +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 somehow these component get rendered twice, but I cannot figure out why.

I've gone trough SO answer but I cant really determine which of the listed causes is the issue in my case. I don't use any bindings.

What I tried so far: played around with setting id excplicitly, i.e. surrounding mycomonent with , passing loop-counters as ID to the component etc.. with no success. I think the problem cannot be solved within mycomponent . The only workaround I found was to make a physical copy of mycomponent and refer to that copy in my anotherForm (such that editItemDlg and anotherDlg do not use the same components).

Any help is appreciated


回答1:


You should not assign an id for your input text on your component.

If you are looping through an array on your form, it's certain that your input text element will be created more than once.

The specified identifier must be unique among all the components (including facets) that are descendents of the nearest ancestor UIComponent that is a NamingContainer, or within the scope of the entire component tree if there is no such ancestor that is a NamingContainer.

As stated on UINamingContainer.

Let's consider that your controller.allArgs has two items on list.

Your generated output:

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

And this'll cause a duplicated id exception.

You could create a new naming container to keep your input id unique or append an index information on your add.




回答2:


What you have right now is multiple JSF components with the same ID, which is not going to work..

When dynamically generating components you have to append some kind of an iteration index to the respective ids.

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

The best thing you can do though is remove the id tag completely and let JSF auto-generate them.

If, of course you do not refence those ids from somewhere else.



来源:https://stackoverflow.com/questions/33258296/duplicate-component-id-in-jsf-using-composite-component-twice-in-view

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!