¿Cómo incluir otro XHTML en XHTML usando JSF 2.0 Facelets?

218

¿Cuál es la forma más correcta de incluir otra página XHTML en una página XHTML? He estado intentando diferentes formas, ninguna de ellas está funcionando.

Ikthiander
fuente

Respuestas:

423

<ui:include>

La forma más básica es <ui:include>. El contenido incluido debe colocarse dentro <ui:composition>.

Ejemplo de inicio de la página maestra /page.xhtml:

<!DOCTYPE html>
<html lang="en"
    xmlns="http://www.w3.org/1999/xhtml"
    xmlns:f="http://xmlns.jcp.org/jsf/core"
    xmlns:h="http://xmlns.jcp.org/jsf/html"
    xmlns:ui="http://xmlns.jcp.org/jsf/facelets">
    <h:head>
        <title>Include demo</title>
    </h:head>
    <h:body>
        <h1>Master page</h1>
        <p>Master page blah blah lorem ipsum</p>
        <ui:include src="/WEB-INF/include.xhtml" />
    </h:body>
</html>

La página de inclusión /WEB-INF/include.xhtml(sí, este es el archivo en su totalidad, las etiquetas externas <ui:composition>son innecesarias ya que Facelets las ignora de todos modos):

<ui:composition 
    xmlns="http://www.w3.org/1999/xhtml"
    xmlns:f="http://xmlns.jcp.org/jsf/core"
    xmlns:h="http://xmlns.jcp.org/jsf/html"
    xmlns:ui="http://xmlns.jcp.org/jsf/facelets">
    <h2>Include page</h2>
    <p>Include page blah blah lorem ipsum</p>
</ui:composition>
  

Esto necesita ser abierto por /page.xhtml. Tenga en cuenta que no necesita repetir <html>, <h:head>y <h:body>dentro del archivo de inclusión ya que de lo contrario se generaría un HTML no válido .

Puede usar una expresión EL dinámica en <ui:include src>. Consulte también ¿Cómo ajax-refresh dynamic incluye contenido por menú de navegación? (JSF SPA) .


<ui:define>/ /<ui:insert>

Una forma más avanzada de incluir es la plantilla . Esto incluye básicamente al revés. La página de plantilla maestra debe usarse <ui:insert>para declarar lugares para insertar contenido de plantilla definido. La página del cliente de plantilla que usa la página de plantilla maestra debe usarse <ui:define>para definir el contenido de la plantilla que se va a insertar.

Página de plantilla maestra /WEB-INF/template.xhtml(como sugerencia de diseño: el encabezado, el menú y el pie de página pueden ser <ui:include>archivos):

<!DOCTYPE html>
<html lang="en"
    xmlns="http://www.w3.org/1999/xhtml"
    xmlns:f="http://xmlns.jcp.org/jsf/core"
    xmlns:h="http://xmlns.jcp.org/jsf/html"
    xmlns:ui="http://xmlns.jcp.org/jsf/facelets">
    <h:head>
        <title><ui:insert name="title">Default title</ui:insert></title>
    </h:head>
    <h:body>
        <div id="header">Header</div>
        <div id="menu">Menu</div>
        <div id="content"><ui:insert name="content">Default content</ui:insert></div>
        <div id="footer">Footer</div>
    </h:body>
</html>

Página del cliente de plantilla /page.xhtml(tenga en cuenta el templateatributo; también aquí, este es el archivo en su totalidad):

<ui:composition template="/WEB-INF/template.xhtml"
    xmlns="http://www.w3.org/1999/xhtml"
    xmlns:f="http://xmlns.jcp.org/jsf/core"
    xmlns:h="http://xmlns.jcp.org/jsf/html"
    xmlns:ui="http://xmlns.jcp.org/jsf/facelets">

    <ui:define name="title">
        New page title here
    </ui:define>

    <ui:define name="content">
        <h1>New content here</h1>
        <p>Blah blah</p>
    </ui:define>
</ui:composition>

Esto necesita ser abierto por /page.xhtml. Si no hay <ui:define>, entonces <ui:insert>se mostrará el contenido predeterminado dentro , si lo hay.


<ui:param>

Puede pasar parámetros <ui:include>ao <ui:composition template>por <ui:param>.

<ui:include ...>
    <ui:param name="foo" value="#{bean.foo}" />
</ui:include>
<ui:composition template="...">
    <ui:param name="foo" value="#{bean.foo}" />
    ...
</ui:composition >

Dentro del archivo de inclusión / plantilla, estará disponible como #{foo}. En caso de que necesite pasar "muchos" parámetros a <ui:include>, entonces será mejor que considere registrar el archivo de inclusión como un archivo de etiquetas, para que finalmente pueda usarlo así <my:tagname foo="#{bean.foo}">. Consulte también ¿ Cuándo usar <ui: include>, archivos de etiquetas, componentes compuestos y / o componentes personalizados?

Incluso puede pasar frijoles enteros, métodos y parámetros a través de <ui:param>. Vea también JSF 2: ¿cómo pasar una acción que incluye un argumento para ser invocado a una subvista Facelets (usando ui: include y ui: param)?


Consejos de diseño

Los archivos a los que no se debe acceder públicamente simplemente ingresando / adivinando su URL, deben colocarse en la /WEB-INFcarpeta, como el archivo de inclusión y el archivo de plantilla en el ejemplo anterior. Consulte también ¿Qué archivos XHTML necesito poner en / WEB-INF y cuáles no?

No es necesario que haya ningún marcado (código HTML) fuera <ui:composition>y <ui:define>. Puedes poner cualquiera, pero Facelets los ignorará . Poner marcado allí solo es útil para diseñadores web. Consulte también ¿Hay alguna forma de ejecutar una página JSF sin construir todo el proyecto?

El doctype HTML5 es el doctype recomendado en estos días, "a pesar de" que es un archivo XHTML. Debería ver XHTML como un lenguaje que le permite producir resultados HTML utilizando una herramienta basada en XML. Consulte también ¿Es posible usar JSF + Facelets con HTML 4/5? y JavaServer Faces 2.2 y compatibilidad con HTML5, ¿por qué se sigue utilizando XHTML ?

Los archivos CSS / JS / imagen se pueden incluir como recursos dinámicamente reubicables / localizados / versionados. Consulte también ¿Cómo hacer referencia al recurso CSS / JS / imagen en la plantilla Facelets?

Puede colocar archivos Facelets en un archivo JAR reutilizable. Consulte también Estructura para múltiples proyectos JSF con código compartido .

Para ver ejemplos del mundo real de plantillas avanzadas de Facelets, consulte la src/main/webappcarpeta del código fuente de la aplicación Java EE Kickoff y el código fuente del sitio de OmniFaces .

BalusC
fuente
1
Hola Balus, con respecto a: La forma más básica es <ui: include>. El contenido incluido debe colocarse dentro de <ui: composition>. Creo que el contenido incluido puede estar simplemente en <p> </p> y funcionará.
Koray Tugay
1
@KorayTugay: Sí, eso es correcto. ui: la composición solo es necesaria para a) usar una plantilla (ver arriba) ob) para envolver todo en <html> <body> para que pueda cargar el archivo con un navegador o editor HTML.
sleske
Hola, ¿puedes resolver este acertijo por mí? He estado golpeando mi cabeza desde hace 3 días. stackoverflow.com/questions/24738079/…
Kishor Prakash
1
@Odysseus: no si en realidad es una composición.
BalusC
1
Afaik si solo declara <ui:composition ...>dentro de facelet, también debe declarar el doctype <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">, de lo contrario, obtendrá un entity referenced but not declarederror al usar entidades HTML.
ChristophS
24

Página incluida:

<!-- opening and closing tags of included page -->
<ui:composition ...>
</ui:composition>

Incluyendo página:

<!--the inclusion line in the including page with the content-->
<ui:include src="yourFile.xhtml"/>
  • Comienza el archivo xhtml incluido con el ui:compositionque se muestra arriba.
  • Incluye ese archivo con ui:includeel archivo xhtml incluido, como también se muestra arriba.
Benchik
fuente
A veces no es suficiente identificar la ruta mientras usas solo un nombre de archivo. Para aquellos que probaron la inclusión de archivos anterior y no funcionó. Puede intentar agregar un símbolo de barra diagonal antes del nombre del archivo o el directorio / WEB-INF. Así parece <ui:include src="/yourFile.xhtml"/>o<ui:include src="/WEB-INF/yourFile.xhtml"/>
Lefan