JSTL en JSF2 Facelets … tiene sentido?

Me gustaría dar salida un poco de código de Facelets condicionalmente.

Para ese propósito, las tags JSTL parecen funcionar bien:

 ...  

Sin embargo, no estoy seguro si esta es una mejor práctica? ¿Hay alguna otra manera de lograr mi objective?

Introducción

Las tags JSTL son todas manejadoras de tags y se ejecutan durante el tiempo de comstackción de la vista , mientras que las tags JSF son todos componentes de la IU y se ejecutan durante el tiempo de visualización de la vista .

Tenga en cuenta que desde las propias tags y de JSF solo aquellas que no se extienden desde UIComponent son también manejadores de tags, por ejemplo , , , etc. Los que se extienden desde UIComponent también son componentes JSF UI, por ejemplo , , , etc. Desde los componentes JSF UI, solo los atributos id y binding también se evalúan durante el tiempo de comstackción view . Por lo tanto, la respuesta a continuación en cuanto al ciclo de vida JSTL también se aplica a los atributos de id y binding de los componentes JSF.

El tiempo de comstackción de la vista es el momento en que el archivo XHTML / JSP debe analizarse y convertirse en un árbol de componentes JSF que luego se almacena como UIViewRoot de FacesContext . El tiempo de visualización de vista es el momento en que el árbol de componentes JSF está a punto de generar HTML, comenzando con UIViewRoot#encodeAll() . Entonces: los componentes JSF UI y las tags JSTL no se ejecutan sincronizados como cabría esperar de la encoding. Puede visualizarlo de la siguiente manera: JSTL se ejecuta de arriba a abajo primero, produciendo el árbol de componentes JSF, luego le toca a JSF volver a ejecutar de arriba a abajo, produciendo la salida HTML.

vs

Por ejemplo, este marcado de Facele itera sobre 3 elementos usando :

    

… crea durante el tiempo de comstackción de vista tres componentes en el árbol de componentes JSF, aproximadamente representados así:

    

… que a su vez generan individualmente su salida de HTML durante el tiempo de visualización de la vista:

 value1 value2 value3 

Tenga en cuenta que debe garantizar manualmente la exclusividad de los ID de los componentes y que también se evalúan durante el tiempo de comstackción de la vista.

Mientras que este marcado de Facele itera sobre 3 elementos usando , que es un componente de UI JSF:

    

… ya termina como está en el árbol de componentes JSF por el cual el mismo componente se ve reutilizado durante la visualización del tiempo de renderizado para generar un resultado HTML basado en la ronda de iteración actual:

 value1 value2 value3 

Tenga en cuenta que el como componente de NamingContainer ya garantiza la exclusividad de la ID del cliente en función del índice de iteración; tampoco es posible usar EL en el atributo id de los componentes secundarios de esta manera, ya que también se evalúa durante el tiempo de comstackción de la vista, mientras que #{item} solo está disponible durante el tiempo de visualización de la vista. Lo mismo es cierto para una h:dataTable y componentes similares.

/ vs rendered

Como otro ejemplo, este marcado de Facelets agrega de manera condicional tags diferentes usando (también puede usar para esto):

          

… en el caso de type = TEXT solo agregará el componente al árbol de componentes JSF:

  

Mientras que este marcado de Facelets:

    

… terminará exactamente como arriba en el árbol de componentes JSF, independientemente de la condición. Esto puede terminar en un árbol de componentes “hinchado” cuando tiene muchos de ellos y en realidad se basan en un modelo “estático” (es decir, el field no cambia durante al menos el scope de la vista). Además, puede encontrarse con un problema EL cuando maneja subclases con propiedades adicionales en las versiones de Mojarra anteriores a la 2.2.7.

vs

No son intercambiables. The establece una variable en el ámbito EL, al que solo se puede acceder después de la ubicación de la etiqueta durante el tiempo de construcción de la vista, pero en cualquier parte de la vista durante el tiempo de visualización de la vista. El pasa una variable EL a una plantilla de Facelet incluida a través de , , o . Las versiones anteriores de JSF tenían errores por los cuales la variable también está disponible fuera de la plantilla de Facelet en cuestión, nunca se debe confiar en esto.

El sin un atributo de scope se comportará como un alias. No almacena en caché el resultado de la expresión EL en ningún ámbito. Por lo tanto, puede perfectamente usarse dentro de, por ejemplo, iterar componentes JSF. Por lo tanto, por ejemplo, a continuación funcionará bien:

     

No es adecuado, por ejemplo, para calcular la sum en un bucle. Para eso, en su lugar, use la secuencia EL 3.0 :

  ...  

Total price: #{bean.products.stream().map(product->product.price).sum()}

Solo cuando establezca el atributo de scope con una de las request valores permitidos, view , session o application , se evaluará inmediatamente durante el tiempo de construcción de la vista y se almacenará en el scope especificado.

  

Esto se evaluará solo una vez y estará disponible como #{dev} toda la aplicación.

Use JSTL para controlar la construcción de árbol de componentes JSF

El uso de JSTL solo puede generar resultados inesperados cuando se utiliza dentro de componentes JSF, como , , etc., o cuando los atributos de la etiqueta JSTL dependen de los resultados de los eventos JSF como preRenderView o los valores de formularios enviados en el modelo que no está disponible durante el tiempo de comstackción de vista. Por lo tanto, use tags JSTL solo para controlar el flujo de creación de árbol de componentes JSF. Use los componentes de la interfaz de usuario JSF para controlar el flujo de generación de salida HTML. No vincule la var de iteración de componentes JSF a atributos de etiqueta JSTL. No confíe en los eventos JSF en los atributos de etiqueta JSTL.

Cada vez que crea que necesita vincular un componente al bean de respaldo a través del binding , o agarrar uno a través de findComponent() , y crear / manipular sus hijos usando código Java en un bean de respaldo con un new SomeComponent() y lo que no, entonces debe inmediatamente detente y considera usar JSTL en su lugar. Como JSTL también está basado en XML, el código necesario para crear componentes JSF de forma dinámica será mucho más legible y mantenible.

Es importante saber que las versiones de Mojarra anteriores a 2.1.18 tenían un error en el ahorro de estado parcial al hacer referencia a un bean de ámbito de vista en un atributo de etiqueta JSTL. Toda la vista de ámbito de bean se recrearía nuevamente en lugar de recuperarse del árbol de vista (simplemente porque el árbol de vista completo aún no está disponible en el punto donde se ejecuta JSTL). Si está esperando o almacenando algún estado en la vista del bean con ámbito por un atributo de etiqueta JSTL, entonces no devolverá el valor que espera, o se “perderá” en el bean de ámbito de vista real que se restaura después de la vista árbol está construido. En caso de que no pueda actualizar a Mojarra 2.1.18 o posterior, lo que resta es desactivar el ahorro de estado parcial en web.xml como se muestra a continuación:

  javax.faces.PARTIAL_STATE_SAVING false  

Ver también:

  • ¿Cuál es el tiempo de construcción de la vista?
  • ¿Cómo funciona el atributo ‘vinculante’ en JSF? ¿Cuándo y cómo se debe usar?
  • ¿Cómo refactorizar fragmento de JSP antiguo a un equivalente de JSF?
  • ¿Debería PARTIAL_STATE_SAVING establecerse en falso?
  • Comunicación en JSF 2.0 – @ViewScoped falla en los controladores de tags

Para ver algunos ejemplos del mundo real en los que las tags JSTL son útiles (es decir, cuando se utilizan de forma correcta durante la construcción de la vista), consulte las siguientes preguntas / respuestas:

  • ¿Cómo hacer una grilla del componente compuesto JSF?
  • Crear columnas de tabla dinámicamente en JSF
  • Cómo personalizar el diseño h: selectOneRadio
  • Definición de variable condicional en JSF
  • Cómo hacer un componente compuesto similar a
  • JSF 2 – Componente compuesto con atributo de escucha opcional en f: ajax
  • Componentes compuestos JSF nesteds que conducen a una excepción de desbordamiento de stack

En una palabra

En cuanto a su requisito funcional concreto, si desea representar componentes JSF condicionalmente, utilice el atributo rendered en el componente HTML JSF, particularmente si #{lpc} representa el elemento iterado actualmente de un componente JSF como o .

  ...  

O bien, si desea construir (crear / agregar) componentes JSF condicionalmente, entonces continúe usando JSTL. Es mucho mejor que verbosely haciendo un new SomeComponent() en java.

   ...   

Ver también:

  • Visualización condicional de componentes JSF
  • JSTL c: si no funciona dentro de un JSF h: dataTable
  • Especifique la representación condicional del elemento dentro de ? El no parece funcionar

utilizar

  ...  

Perdón por la respuesta por separado, pero no pude comentar las respuestas anteriores.

Para la salida tipo interruptor, puede usar el interruptor de las primas-extensiones .