tags:

views:

761

answers:

2
+1  Q: 

Duplicate Id. JSF

Hi! I have a problem with JSF. Can anyone say why this doesn't work?

<h:selectOneListbox
  id="lang" size="5"
  value="#{MbInstitution.node.lang}"
  valueChangeListener="#{MbInstitution.changeLanguage}"
  rendered="#{MbInstitution.view}"
  >
 <a4j:support event="onchange" reRender="shortDesc, fullDesc"/>
 <f:selectItems value="#{MbInstitution.languagesByInstitute}"/>
</h:selectOneListbox>
<h:selectOneListbox
  id="lang" size="5"
  disabled="#{!MbInstitution.managingNew}"
  value="#{MbInstitution.node.lang}"
  rendered="#{!MbInstitution.view}"
  >
 <f:selectItems value="#{MbInstitution.availableLanguages}"/>
</h:selectOneListbox>

It says: "duplicate Id for a component instForm:lang" I know that i have 2 elements with same Id, but one is rendered only when another isn't. So, i didn't think it would be a problem. Actually it's not a big problem at all as i don't need this id, but what if i needed then what would i do?

+1  A: 

You'll have to use a different ID or put it in another naming container.

The Javadoc for UIComponent.setId() says:

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.

Wayne Young
+3  A: 

Your problem is that these two components are part of the JSF Component tree for this page. And even if they cannot be displayed at the same time, they share the same ID, which is not allowed by JSF.

I see three solutions to solve your problem:

First solution: Define two differents ID

Second solution: You can, as explained by Wayne Young, use a NamingContainer, which will prefix their ID by the ID of the NamingContainer.

Third solution: Use only one <h:selectOneListbox/> and then make the difference in the Java code.

<h:selectOneListbox id="lang" size="5" disabled="#{!MbInstitution.managingNew}" value="#{MbInstitution.node.lang}" valueChangeListener="#{MbInstitution.changeLanguage}">
    <a4j:support event="onchange" reRender="shortDesc, fullDesc" rendered="#{MbInstitution.view}"/>
    <f:selectItems value="#{MbInstitution.languages}"/>
</h:selectOneListbox>

Java code:

public List<SelectItem> getLanguage() {
    if (isView()) {
        return getLanguagesByInstitute();
    } else {
        return getAvailableLanguages();
    }
}

public void changeLanguage(ValueChangeEvent evt) {
    if (!isView()) {
        return;
    }
    ...
}
romaintaz
Thanks! That's just what i wanted (third solution). It's so simple that i'm confused i couldn't find it by myself. :)
mykola