I have a <ui:composition> that contains a few elements with explicit ids and some ajax events which reference these ids for partial processing/updating. I encapsulated this fragment of xhtml inside the composition simply so I could use it in a few different places without having to duplicate the code. However, when I use the composition (with <ui:include>) more than once inside a page, I get duplicate id exceptions. It seems JSF is not wrapping each composition inside its own naming container (like <ui:component> does).
Is there a simple way to wrap my composition inside its own naming container? Or do I have to use a composite component every time I want to reuse xhtml fragments inside a common naming container?
Depending on the purpose of the <ui:include> template, you've several options:
Use <f:subview>. It creates another NamingContainer context (like as <h:form>, <h:dataTable>, and friends all do):
<f:subview id="top">
    <ui:include src="/WEB-INF/includes/some.xhtml" />
</f:subview>
...
<f:subview id="bottom">
    <ui:include src="/WEB-INF/includes/some.xhtml" />
</f:subview>
The components definied in some.xhtml will end up getting respectively top: and bottom: prefix in their ID.
Turn it into a tagfile which requires an id attribute.
<my:some id="top" />
...
<my:some id="bottom" />
And use that ID to prefix the ID of the components in the composition.
<ui:composition 
    xmlns="http://www.w3.org/1999/xhtml"
    xmlns:f="http://java.sun.com/jsf/core"
    xmlns:h="http://java.sun.com/jsf/html"
    xmlns:ui="http://java.sun.com/jsf/facelets"
>
    ...
    <h:someComponent id="#{id}_some" />
    <h:otherComponent id="#{id}_other" />
    ...
<ui:composition>
Turn it into a composite component. Composite components are inherently already a NamingContainer, so their id attribute is optional. Basically, replace 
<ui:composition 
    xmlns="http://www.w3.org/1999/xhtml"
    xmlns:f="http://java.sun.com/jsf/core"
    xmlns:h="http://java.sun.com/jsf/html"
    xmlns:ui="http://java.sun.com/jsf/facelets"
>
    ...
<ui:composition>
by
<ui:component 
    xmlns="http://www.w3.org/1999/xhtml"
    xmlns:f="http://java.sun.com/jsf/core"
    xmlns:h="http://java.sun.com/jsf/html"
    xmlns:ui="http://java.sun.com/jsf/facelets"
    xmlns:cc="http://java.sun.com/jsf/composite"
>
    <cc:interface>
        <!-- This is optional. -->
    </cc:interface>
    <cc:implementation>
        ...
        <h:someComponent id="some" />
        <h:otherComponent id="other" />
        ...
    </cc:implementation>
<ui:component>
This way you can use it as follows:
<my:some id="top" />
...
<my:some id="bottom" />
The components definied in <cc:implementation> will end up getting respectively top: and bottom: prefix in their ID  (note again, the composite component's id attribute is optional, JSF will otherwise autogenerate one).
When you include more than once the same ui:composition the id are duplicated. The solution is to specifiy a particular ui:param within the ui:include.
Assuming you're including mycomposition.xhtml you can do something similar:
<ui:include src="mycomposition.xhtml">
    <ui:param name="idPrefix" value="first"/>
</ui:include>
...
<ui:include src="mycomposition.xhtml">
    <ui:param name="idPrefix" value="second"/>
</ui:include>
Then in the mycomposition.xhtml you should declare the ids as follows (for instance a h:outputText):
<h:outputText id="#{idPrefix}_text" value="My Awesome Text here"/>
Now you can reference the id in the rest of yout page as #{idPrefix}_text.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With