22

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?

1
  • 3
    I haven't had to use it, but wrapping the composition contents in a f:subView seems to help, as described in this answer. Commented Feb 4, 2014 at 13:08

2 Answers 2

40

Depending on the purpose of the <ui:include> template, you've several options:

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


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

  3. 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:

Sign up to request clarification or add additional context in comments.

2 Comments

Thanks once again @BalusC. I thought you must be able to do something like the <f:subview> option - good to know.
@BalusC , if I use this f:subview , can I continue using the java scripts in the same manner ? or javascripts (which using ids of the page) need to change accordingly?
8

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.

Comments

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.