Avoiding duplicate ids when reusing facelets compositions in the same naming container

composition, facelets, jsf, jsf-2

Solution

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

See also:

- When to use <ui:include>, tag files, composite components and/or custom components?

Problem

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?

Original source

Related problems