jsf jsf-2 conditional uiinclude rendered-attribute

JSF condicional incluye, porque el ID del componente ya se ha encontrado en la vista



jsf-2 conditional (1)

Sé que no podemos repetir la ID de ningún componente que tengamos en el mismo árbol de vista.

Tengo una página que incluye otras páginas por cierta condición, como esta ...

<h:panelGroup rendered="#{bean.insertMode == ''SINGLE''}"> <ui:include src="_single.xhtml" /> </h:panelGroup> <h:panelGroup rendered="#{bean.insertMode == ''DOUBLE''}"> <ui:include src="_double.xhtml" /> </h:panelGroup>

Ahora en estas páginas tengo "Casi" la misma jerarquía de componentes (Complejo) con diferentes acciones (no solo llamadas de método, sino también vistas), por ejemplo:

_single.xhtml

<p:inputText id="fieldID" value="#{bean.value}" /> <p:commandLink actionListener="#{bean.singleAction()}" />

_double.xhtml

<p:inputText id="fieldID" value="#{bean.value}" /> <p:commandLink actionListener="#{bean.doubleAction()}" />

Mi pequeño ejemplo funciona bien, y rinde como se supone, pero me sale

java.lang.IllegalStateException: Component ID fieldID has already been found in the view.

Sé que JSF procesa las páginas completas incluso si no están incluidas y es por eso que recibo esta excepción.

Cualquier forma inteligente de resolver esto sin cambiar los ID de los componentes dentro de las páginas de inclusión (aunque funciona, pero la excepción es molesta y parece que algo está mal).

No quiero también envolver cada una de las páginas con algún componente contenedor con un ID diferente para que tengan un ID COMPLETO diferente como formId: fieldID porque la página maestra también se refiere a estos componentes dentro de estos ¡incluidos!


El error de ID de componente duplicado se produce porque ambas inclusiones terminan físicamente en el árbol de componentes JSF. El <h:panelGroup rendered="false"> no evita que terminen en el árbol de componentes JSF, sino que evita que generen su salida HTML.

En lugar de representar condicionalmente su salida HTML, debe compilarlos condicionalmente en el árbol de componentes JSF. JSTL es muy útil en esto, ya que se ejecuta durante el tiempo de compilación de la vista:

<c:if test="#{bean.insertMode eq ''SINGLE''}"> <ui:include src="_single.xhtml" /> </c:if> <c:if test="#{bean.insertMode eq ''DOUBLE''}"> <ui:include src="_double.xhtml" /> </c:if>

En caso de que estés usando Mojarra, solo necesitas asegurarte de usar al menos la versión 2.1.18 o más reciente, de lo contrario, los frijoles de vista se comportarán como los frijoles de solicitud.

Una alternativa es hacer uso del operador condicional EL en el atributo src (el <ui:include> se ejecuta como un manejador de etiquetas también durante el tiempo de compilación de la vista):

<ui:include src="_#{bean.insertMode eq ''SINGLE'' ? ''single'' : ''double''}.xhtml" />

O incluso use el insertMode directamente como nombre de archivo:

<ui:include src="_#{fn:toLowerCase(bean.insertMode)}.xhtml" />

De cualquier manera, debe asegurarse de que el #{bean.insertMode} esté disponible durante el tiempo de compilación de la vista, y también que exactamente el mismo valor esté disponible durante la fase de restauración de las devoluciones de datos que durante el procesamiento inicial; posiblemente se restauraría con la inclusión incorrecta y JSF ya no puede decodificar las entradas y el comando correctos. Además, cuando desea cambiar la inclusión durante la devolución, realmente necesita reconstruir la vista (devolver no null / void ) o enviar un redireccionamiento.

Ver también: