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