2

I'm writing a Facelets composite component that switches between using inputText and inputSecret based on a parameter:

<composite:interface>
    <composite:attribute name="myId" required="true"/>
    <composite:attribute name="secret" required="false" default="false" />
</composite:interface>

<composite:implementation>
    <h:inputSecret rendered="#{cc.attrs.secret}" id="#{cc.attrs.myId}" />
    <h:inputText rendered="#{!cc.attrs.secret}" id="#{cc.attrs.myId}" />
</composite:implementation>

The problem is that I get the following error:

Component ID [JSF mangled id] has already been found in the view.

BalusC
  • 1,082,665
  • 372
  • 3,610
  • 3,555
user694759
  • 35
  • 5

2 Answers2

4

Use a view build time tag like JSTL <c:if> or <c:choose> instead of the JSF component's rendered attribute. View build time tags are evaluated during constructing the JSF component tree, while the rendered attribute is only evaluated during generating HTML based on the JSF component tree (and thus you still end up with both components with the same ID in the JSF component tree!).

E.g.

<c:if test="#{not cc.attrs.secret}">
    <h:inputText id="input" />
</c:if>
<c:if test="#{cc.attrs.secret}">
    <h:inputSecret id="input" />
</c:if>

See also:


Unrelated to the concrete problem, the myId doesn't make sense. Just give those a fixed ID. In case the reason was the inability to reference them from outside by ajax, head to Referring composite component ID in f:ajax render.

Community
  • 1
  • 1
BalusC
  • 1,082,665
  • 372
  • 3,610
  • 3,555
0

Whether or not the component is actually rendered doesn't matter.Both components will still exist in the view's internal component tree and will require a unique id. We ran into this problem as well.

We suffixed the id with a _1 and _2 and if we need to get a hold of the id inside javaScript, we use JQuery's partial matchers.

In your case, can you not make your bean's getMyId() method return a different id based on the value of the secret property?

Steve Atkinson
  • 1,219
  • 2
  • 12
  • 30