Como incluir outro XHTML no XHTML usando o JSF 2.0 Facelets?

218

Qual é a maneira mais correta de incluir outra página XHTML em uma página XHTML? Eu tenho tentado maneiras diferentes, nenhum deles está funcionando.

Ikthiander
fonte

Respostas:

423

<ui:include>

Maneira mais básica é <ui:include>. O conteúdo incluído deve ser colocado dentro <ui:composition>.

Exemplo inicial da página principal /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>

A página de inclusão /WEB-INF/include.xhtml(sim, este é o arquivo na íntegra, quaisquer tags externas <ui:composition>são desnecessárias, pois são ignoradas pelo Facelets de qualquer maneira):

<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>
  

Isso precisa ser aberto por /page.xhtml. Note que você não precisará repetir <html>, <h:head>e <h:body>dentro do arquivo de inclusão como que de outra forma resultar em inválido HTML .

Você pode usar uma expressão EL dinâmica em <ui:include src>. Consulte também Como incluir conteúdo dinâmico da ajax-refresh pelo menu de navegação? (SPA JSF) .


<ui:define>/<ui:insert>

Uma maneira mais avançada de incluir é o modelo . Isso inclui basicamente o contrário. A página do modelo mestre deve ser usada <ui:insert>para declarar locais para inserir o conteúdo do modelo definido. A página do cliente de modelo que está usando a página de modelo principal deve ser usada <ui:define>para definir o conteúdo do modelo a ser inserido.

Página principal do modelo /WEB-INF/template.xhtml(como uma dica de design: o cabeçalho, o menu e o rodapé podem, por sua vez, ser <ui:include>arquivos):

<!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 do cliente do modelo /page.xhtml(observe o templateatributo; também aqui, este é o arquivo na sua totalidade):

<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>

Isso precisa ser aberto por /page.xhtml. Se não houver <ui:define>, o conteúdo padrão interno <ui:insert>será exibido, se houver.


<ui:param>

Você pode passar parâmetros para <ui:include>ou <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 do arquivo include / template, ele estará disponível como #{foo}. Caso você precise passar "muitos" parâmetros para <ui:include>, considere registrar o arquivo de inclusão como um arquivo de tag, para que você possa usá-lo dessa maneira <my:tagname foo="#{bean.foo}">. Consulte também Quando usar <ui: include>, arquivos de tags, componentes compostos e / ou componentes personalizados?

Você pode até passar feijões inteiros, métodos e parâmetros via <ui:param>. Consulte também JSF 2: como passar uma ação incluindo um argumento a ser invocado para uma subvisualização do Facelets (usando ui: include e ui: param)?


Dicas de design

Os arquivos que não deveriam estar acessíveis ao público apenas digitando / adivinhando sua URL, precisam ser colocados na /WEB-INFpasta, como o arquivo de inclusão e o modelo no exemplo acima. Veja também Quais arquivos XHTML eu preciso colocar em / WEB-INF e quais não?

Não precisa haver nenhuma marcação (código HTML) fora <ui:composition>e <ui:define>. Você pode colocar qualquer um, mas eles serão ignorados pelo Facelets. Colocar a marcação lá é útil apenas para web designers. Consulte também Existe uma maneira de executar uma página JSF sem construir todo o projeto?

O doctype HTML5 é o doctype recomendado atualmente ", apesar de" ser um arquivo XHTML. Você deve ver o XHTML como uma linguagem que permite produzir saída HTML usando uma ferramenta baseada em XML. Consulte também É possível usar o JSF + Facelets com HTML 4/5? e suporte ao JavaServer Faces 2.2 e HTML5, por que o XHTML ainda está sendo usado .

Os arquivos CSS / JS / imagem podem ser incluídos como recursos relocáveis ​​dinamicamente / localizados / com versão. Consulte também Como referenciar CSS / JS / recurso de imagem no modelo Facelets?

Você pode colocar arquivos Facelets em um arquivo JAR reutilizável. Consulte também Estrutura para vários projetos JSF com código compartilhado .

Para obter exemplos reais do modelo avançado de Facelets, verifique a src/main/webapppasta do código-fonte do Java EE Kickoff App e o OmniFaces mostra o código-fonte do site .

BalusC
fonte
1
Oi Balus, sobre: ​​A maneira mais básica é <ui: include>. O conteúdo incluído deve ser colocado dentro de <ui: composition>. Acho que o conteúdo incluído pode simplesmente estar em <p> </p>, ele funcionará.
Koray Tugay
1
@KorayTugay: Sim, está correto. ui: composition é apenas necessário para a) usar um modelo (veja acima) ou b) para agrupar tudo em <html> <body> para que você possa carregar o arquivo com um navegador ou editor de HTML.
sleske
Oi, você pode resolver este enigma para mim? Eu tenho batido minha cabeça nos últimos 3 dias. stackoverflow.com/questions/24738079/…
Kishor Prakash
1
@ Odysseus: não se for realmente uma composição.
precisa saber é o seguinte
1
Além disso, se apenas declarando <ui:composition ...>dentro do facelet você tiver que declarar o doctype como <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">também, caso contrário, você receberá um entity referenced but not declarederro ao usar entidades HTML.
ChristophS
24

Página incluída:

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

Incluindo página:

<!--the inclusion line in the including page with the content-->
<ui:include src="yourFile.xhtml"/>
  • Você inicia o arquivo xhtml incluído ui:compositioncomo mostrado acima.
  • Você inclui esse arquivo ui:includeno arquivo xhtml incluído, como também mostrado acima.
Benchik
fonte
Às vezes, não é suficiente identificar o caminho enquanto você usa apenas um nome de arquivo. Para aqueles que tentaram a inclusão de arquivo acima e não funcionou. Você pode tentar adicionar um símbolo de barra antes do nome do arquivo ou do diretório / WEB-INF. Assim parece <ui:include src="/yourFile.xhtml"/>ou<ui:include src="/WEB-INF/yourFile.xhtml"/>
Lefan 04/12/19