Facelets y uso de templates en JSF

Facelets es un lenguaje de declaración de vistas para JavaServer Faces, que permite crear vistas usando templates HTML, crear árboles de componentes, favorece la reutilización de código, y es especialmente útil cuando nuestro sitio tiene muchas páginas que comparten un mismo layout (por ejemplo, mismo header y footer).

Para permitir agregar componentes a nuestras páginas JavaServer Faces soporta la utilización de las siguientes tag libraries:

LibreríaURIPrefijoDescripción
Faceletshttp://java.sun.com/jsf/faceletsui:tags para trabajar con templates
HTMLhttp://java.sun.com/jsf/htmlh:tags de componentes JSF
Corehttp://java.sun.com/jsf/coref:tags para acciones personalizadas
JSTL Corehttp://java.sun.com/jsp/jstl/corec:Etiquetas principales de JSTL 1.2
JSTL Functionshttp://java.sun.com/jsp/jstl/functionsfn:Etiquetas de funciones de JSTL 1.2

Templates en Facelets

Una plantilla o template es una página (xhtml) que no está destinada a albergar contenido propiamente dicho, sino que es utilizada para definir una estructura o layout y especifica áreas donde se insertarán páginas de contenido.

Esto significa que el layout de una parte o la totalidad de las páginas de un sitio se codificará una sola vez. Las páginas de contenido simplemente harán referencia al template correspondiente. Esto favorece la reutilización de código.

El siguiente gráfico muestra cómo un único template o layout es utilizado por todas las páginas de la aplicación. De esta forma, las secciones comunes a toda la aplicación son reutilizadas evitando la necesidad de tener que reescribirlas o importarlas manualmente en cada página.

Templates en Facelets

Creación del template

Para la creación del template partiremos de una vista cuyo body dividiremos en tres secciones principales (header, content y footer). Demarcaremos cada sección con una etiqueta <div>.

layout.xhtml

<html lang="en"
		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:head>
		<h:outputStylesheet library="css" name="styles.css" />
	</h:head>
	<h:body>
		<div id="header">
			<h1>This is HEADER</h1>
		</div>
		<div id="content">
			<h1>This is DEFAULT CONTENT</h1>
		</div>
		<div id="footer">
			<h1>This is FOOTER</h1>
		</div>
	</h:body>
</html>

Declaración del área de contenido en el template

Definiremos el área donde queremos insertar el contenido con el tag <ui:insert>. El atributo name nos servirá para hacer referencia a esta área desde la página de contenido correspondiente. En <ui:insert> también podemos agregar contenido que se visualizará en caso que accedamos al template directamente (no a través de una vista o página de contenido).

<div id="content">
	<ui:insert name="content">
		<h1>This is DEFAULT CONTENT</h1>
	</ui:insert>
</div>

Se debe tener en cuenta que para poder utilizar el tag <ui:insert> se debe agregar la siguiente tag library:

xmlns:ui="http://java.sun.com/jsf/facelets"

Si se accede a la URL del template se visualizará el contenido por defecto:

Template

Modularización de la estructura del template

Si para nuestra aplicación vamos a utilizar más de un template diferente pero que comparten entre sí secciones similares (por ejemplo, encabezado, pie de página, etc) podemos maximizar la reutilización de código encapsulando estas secciones en archivos xhtml individuales para luego agregarlas al template correspondiente con el tag <ui:include>

layout2.xhtml

<html lang="en"
		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:head>
		<h:outputStylesheet library="css" name="styles.css" />
	</h:head>
	<h:body>
            <div id="header">
                <ui:include src="header.xhtml" />
            </div>
            <!-- 'content' section... -->
            <div id="footer">
                <ui:include src="footer.xhtml" />
            </div>
	</h:body>
</html>

A continuación, en los archivos header.xhtml y footer.xhtml se alojan los componentes que terminarán conformando la cabecera y pie de nuestras páginas. El tag <ui:composition> se utiliza para agrupar los componentes a ser reutilizados por otra vista. Se debe tener en cuenta que cualquier componente ubicado fuera de <ui:composition> no será renderizado.

header.xhtml

<!DOCTYPE html>
<html lang="en"
		xmlns="http://www.w3.org/1999/xhtml"
		xmlns:h="http://java.sun.com/jsf/html"
		xmlns:ui="http://java.sun.com/jsf/facelets">
    <h:body>
    	<ui:composition>
			<h1>This is INCLUDED HEADER</h1>    	
    	</ui:composition>
	</h:body>
</html>

footer.xhtml

<!DOCTYPE html>
<html lang="en"
		xmlns="http://www.w3.org/1999/xhtml"
		xmlns:h="http://java.sun.com/jsf/html"
		xmlns:ui="http://java.sun.com/jsf/facelets">
    <h:body>
    	<ui:composition>
			<h1>This is INCLUDED FOOTER</h1>    	
    	</ui:composition>
	</h:body>
</html>

El resultado muestra una vista similar a la anterior:

Template include

Parametrización de secciones reutilizadas

Las secciones reutilizables pueden necesitar mostrar datos correspondientes a variables que están siendo manejadas por la página que las incluye (template). Por ejemplo, el nombre de usuario en el encabezado. Es posible pasar el parámetro al encabezado utilizando el tag <ui:param>.

En el template se debe agregar el parámetro dentro de <ui:include>:

layout2.xhtml

...

<div id="header">
	<ui:include src="header.xhtml">
		<ui:param name="user" value="John" />
	</ui:include>
</div>

...

En el encabezado hacemos uso de la variable dentro de una expresión:

header.xhtml

...

<ui:composition>
	<h1>This is INCLUDED HEADER</h1>
	<h:outputText value="Welcome: #{user}" />
</ui:composition>

...
Template include con parámetro

Utilización del template creado

Habiendo completado los pasos descritos anteriormente y teniendo completo nuestro template, resta crear las páginas con el contenido que necesitamos mostrar. Para esto utilizaremos nuevamente el tag <ui:composition> pero utilizando el atributo template para indicar cuál es la plantilla o template en la cual se debe insertar el contenido antes de ser renderizado:

<ui:composition template="layout.xhtml">
	...
</ui:composition>

También debemos especificar en qué área (de la(s) definida(s) en el template con el tag <ui:insert>) se debe ubicar el contenido. Esto lo haremos con el tag <ui:define> utilizando el atributo name para especificar el nombre del área:

<ui:define name="content">
	...
</ui:define>

Dentro de <ui:define> colocaremos todo el contenido de la vista actual.

A continuación dos ejemplos de páginas básicas y como se visualizarán enmarcadas en el correspondiente template.

page1.xhtml

<ui:composition template="layout.xhtml"
		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:define name="content">
		<div class="content-block" style="background-color: #FFE87E">
			<h:outputText value="Some random text here." />
		</div>
	</ui:define>
</ui:composition>
Template con contenido 1

page2.xhtml

<ui:composition template="layout.xhtml"
		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:define name="content">
		<div class="content-block" style="background-color: #DAFF7E">
			<h:outputText value="More sample text for demonstration purposes." />
		</div>
	</ui:define>
</ui:composition>
Template con contenido 2

Conclusión

Los templates de Facelets proporcionan una herramienta poderosa para crear páginas web dinámicas y personalizables en una aplicación basada en JSF. Al permitir que los desarrolladores definan plantillas y componentes reutilizables, Facelets agiliza el proceso de desarrollo y promueve la reutilización del código, lo que da como resultado aplicaciones más eficientes y fáciles de mantener. Además, los templates de Facelets ofrecen un alto nivel de flexibilidad y personalización, lo que permite a los desarrolladores crear páginas web adaptadas a las necesidades de sus usuarios. Con su sintaxis intuitiva y sus potentes funciones, los templates de Facelets son un activo valioso en cualquier proyecto de desarrollo de aplicaciones web basado en JSF.


Te puede interesar:

JSF dataTable

JSF dataTable se utiliza para desplegar datos en formato de tabla, renderizando una tabla HTML en forma dinámica.

Seguir leyendo →

Arquitectura y Ciclo de Vida

Cómo funciona el ciclo de vida de una aplicación JSF. En el artículo relacionado se cubre el manejo de eventos.

Seguir leyendo →