21 de março de 2012

JSF 2.0: Template em Facelets com Layout do PrimeFaces 3.0

Olá pessoas!
Depois de meses ausente, estou voltando a escrever mas a partir de agora é sobre a versão 3 do PrimeFaces!
Primeiramente baixe a versão 3.0 do PrimeFaces aqui. Agora vamos criar um projeto, no meu caso o nome  do meu projeto será "template", este terá a seguinte estrutura:

O que eu fiz de diferente... para ficar um projeto mais organizado, eu criei uma pasta tema dentro de Páginas Web, ainda dentro da pasta tema eu criei uma pasta imagens, que é onde eu guardo todas as imagens do design do sistema, nesse caso só coloquei a imagem que será o topo do nosso template.
O principal de tudo isso é o nosso padrao.xhtml que foi criado dentro do tema, ele será o responsável pelo nosso template, nele eu coloco tudo o que será comum a todas as páginas que terão template, por exemplo, o componente growl (que mostra avisos ao usuário, visto em postagens anteriores), além de styles CSS que as vezes é necessário.
O meu template ficará assim:


Então meu template (padrao.xhtml) ficou assim:
<html xmlns="http://www.w3.org/1999/xhtml"
      xmlns:ui="http://java.sun.com/jsf/facelets"
      xmlns:h="http://java.sun.com/jsf/html"
      xmlns:p="http://primefaces.org/ui"
      xmlns:f="http://java.sun.com/jsf/core">

    <h:head>
        <meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
        <title>Meu Sistema</title>
        <style type="text/css">
            body {background-color: #eeeeee; font-size: 12px}
        </style> 
    </h:head>
    <h:body>
        <div align="center">
            <p:layout style="min-width:1020px;max-width:1020px;min-height:600px">  
                <p:layoutUnit position="north" size="100">  
                    <h:graphicImage url="/tema/imagens/topo.jpg" />
                </p:layoutUnit>  

                <p:layoutUnit position="west" size="220">  
                    <ui:insert name="menu">
                        <h:form>
                            <p:menu style="width: 200px">
                                <p:submenu label="Menu">
                                    <p:menuitem value="Login" icon="ui-icon-key" />
                                    <p:menuitem value="Fazer meu cadastro" icon="ui-icon-contact" />         
                                </p:submenu>
                            </p:menu>
                        </h:form>
                    </ui:insert>
                </p:layoutUnit>  
                <p:layoutUnit position="center">  
                    <ui:insert name="centro">
                        O que estiver aqui será substituido!
                    </ui:insert>
                </p:layoutUnit>  
            </p:layout>  
        </div>
    </h:body>
</html>

Vamos às observações quanto ao código:
Linha 4: Devemos observar que para usar a versão 3.0 do PrimeFaces a namespace é outra agora!
Linha 15: Criação de uma div centralizada, pois meu layout deverá ficar centralizado.
O segredo do template estão nas linhas 22 e 34 por conta das tags ui:insert, ou seja são elas que definem onde ficará meus componentes. Perceba que eu já coloquei o menu diretamente no meu template, já que será algo para o projeto inteiro, caso precise de um outro menu para uma página exclusiva, apenas sobrescreva o menu na página que deseja. Observação: sempre fique atento ao name da tag ui:insert, pois são eles que definem o que será o menu, ou que será o centro da nossa página (não é obrigado a usar os mesmos nomes que eu coloquei).
Agora vamos ver como vai ficar nosso index.xhtml:


Veja que só mudou nossa frase do centro... agora vamos ver como usar o tal template!
Página index.xhtml:
<html xmlns="http://www.w3.org/1999/xhtml"
      xmlns:h="http://java.sun.com/jsf/html"
      xmlns:ui="http://java.sun.com/jsf/facelets">
    <ui:decorate template="/tema/padrao.xhtml">
        <ui:define name="centro">
            Aqui é o centro do index!
        </ui:define>
    </ui:decorate>
</html>

Vamos às observações:
1 - veja que na nossa página não temos mais as tags h:head e h:body ... elas foram substituídas pela tag ui:decorate (caso não saiba do que eu estou falando, veja essa postagem sobre facelets) nela eu defino qual é o template que eu estou usando nessa página, ou seja, é possível ter mais de um template no mesmo sistema sem problemas!
2 - observe que eu só sobrescrevi o centro (linha 5), tudo que deve ficar no centro da página deve ficar dentro da tag ui:define.

Conclusão: quando se utilizo templates, temos geralmente apenas uma página que contém h:head e h:body que é o próprio template (a não ser que o sistema tenha outras páginas sem template), quanto as outras páginas com template, elas precisam ter o ui:decorate ou ui:composition (veja a postagem de facelets, link acima). Ao executar seu sistema, olhe o código fonte, e veja que o código do template fica embutido com o código da sua página, como se tudo estivesse na mesma página.

Vantagem: Quer alterar o seu design? Quando começou o sistema o seu design era um, e agora já se cansou dele? Então, essa pode ser uma boa solução para você, pois a vantagem é bem essa, ter que fazer alterações em apenas uma página para trocar o design do sistema inteiro. Imagina o que seria um sistema com 50 páginas sem utilizar template? Seria necessário passar de página por página alterando o design, ainda correndo o risco de deixar uma página de fora das alterações.

Nesse exemplo eu fiz uma junção do componente p:layout do PrimeFaces com o Facelets (responsável pelas tags: ui:insert, ui:define ui:.... etc...), mas se preferir usar CSS, nada te impede, coloque o ui:insert dentro de div formatadas na posição que desejar.

Bom... o post de hoje foi curto, mas espero que seja útil!

38 comentários:

  1. Ola, parabens pelo post, estou tentando dar uma incrementada mas nao estou conseguindo
    criei uma nova pagina xhtml(cadastro.xhtml) onde tem um formulario basico de cadastro
    como eu faço para que essa pagina seja chamada no "Centro" ????sem abrir em uma nova guia??
    abracos
    e parabens

    ResponderExcluir
    Respostas
    1. Este comentário foi removido pelo autor.

      Excluir
    2. Manda um email para: douglaspdc@gmail.com que eu explico.
      Aqui não da pra ler o código direito.

      Abraços

      Excluir
  2. Andii, Excelente trabalho. Venho lendo seus artigos e são muito bons. Além de beleza, inteligência, o mais importante.

    Seguinte, aceita uma sugestão de artigo? Que tal sobre autenticação de usuário com primefaces?

    Fica a dica.

    Sucesso!

    ResponderExcluir
    Respostas
    1. Obrigada Vitor! :)
      Vc diz de juntar o Spring Security com o PrimeFaces? Fazer um layout legal?
      Porque se for só autenticação eu já tenho uma postagem sobre o Spring Security, só que com JSF puro.
      Tenho um projetinho já pra estar criando uma nova postagem sobre ele, mas dessa vez indo mais a fundo, no caso bloquear menus, esconder campos, e claro, com uma página de login do Prime.
      Bom, assim que tiver tempo, coloco isso no blog!

      Grata pela sugestão :)

      Excluir
    2. Na minha aplicação eu estou usando o spring para fazer isso, é muitíssimo fácil. Só vc acertar a configuração, que é receita de bolo, e o colocar as tags de segurança que o spring faz a mágica. Seria um post bacana para passar pro pessoal.

      Excluir
    3. Andii. Isso mesmo. Spring Security com PrimeFaces. Com o controle de acesso que mencionasse.

      Estou no aguardo para conferir mais essa!

      Bom final de semana.

      Excluir
    4. Pablo, a receita básica do Spring Security já tem no blog!
      Só falta a receita Expert hahaha
      Logo logo eu posto ela :)

      Excluir
  3. Poxa, parabéns. Era tudo que precisava pra definir meu layout. Mais uma vez, parabéns!

    ResponderExcluir
  4. Oi só uma pergunta: To reparando que as vzs minhas tabelas ele não ta trazendo, tipo um bug loco, uma hora ta de boa dae quando abro outra página ele não carrega a tabela. Mas é só com minhas datatable, vc sabe o que posso ter colocado errado que esta causando o erro? Teria alguma tag para corrigir isso?

    ResponderExcluir
    Respostas
    1. é a datatable ou os dados dela? Se for a datatable, pode ser que vc esteja usando p:dataTable e h:column (a coluna precisa ser do primefaces também) ... agora se forem os dados, pode ser problema de escopo do bean.

      Excluir
  5. Parabéns pelo post e pelo blog, tem me ajudade bastante com JSF e PrimeFaces.

    ResponderExcluir
  6. Andii, queria tirar um dúvida contigo. Eu criei um template padrão igualzinho o seu, só mudei a imagem do topo e os nomes do menu na lateral. Só que quando faço um teste, só é exibido o retângulo branco no centro (onde os fragmentos de página serão exibidos). O topo com a imagem e o menu lateral ficam escondidos. Verifiquei com o firebug, os mesmos foram renderizados porém estão ocultos. Sabe o que pode ser esse problema?

    Obs: Uso o jsf 2 mojarra e primefaces 2.2.1

    ResponderExcluir
    Respostas
    1. Já resolvi o problema. Alterei para o mojarra 2.1.4, e vi na documentação do primefaces 2.2.1 que algumas propriedades dos componentes mudaram, ex: position="west" do p:layoutUnit = position="left" do p:layoutUnit...valeu!

      Excluir
  7. Andii, soh uma duvida, fazendo teste nesse template, ao tentar colocar uma imagem no layoutunit do TOP, percebi que a imagem nao fica preenchida por completa dentro do quadro.
    tentei e nao consegui. manda um dica. Grato.

    ResponderExcluir
    Respostas
    1. Olá JonathasLopes, não tem dica pra fazer isso, a unica coisa que eu fiz, é a uma imagem pra caber exata dentro do espaço do layoutUnit

      Excluir
  8. Tive uma dúvida sobre o diretório da imagem, vasculhei todos os fóruns, videos e apostilas. Só fui achar aqui! Parabéns, e obrigado pela ajuda!

    ResponderExcluir
  9. Andii olha eu aqui de novo...
    estou com um probleminha, ao utilizar o template vi que as url nao alteram certo? e como utilizo o spring security ele nao intercepta, deixando assim todo o sistema aberto. como posso corrigir isso? por exemplo mesmo usando o template, fazer com que as url sejam alteradas.
    Grato.

    ResponderExcluir
    Respostas
    1. Jonathas, a minha solução é desativar ou esconder os links no menu, faço tipo um controle de usuário, vejo quem é o usuário logado e quais as permissões dele, aí tenho uma classe que é apenas pra controlar essa questão do que o determinado perfil pode ou não acessar

      Excluir
    2. Bom dia andii resolvi usando um atributo, ao inves de action="URL" usei o outcome="URL" no componete do p:menuitem. url sem o contexto da aplicação.
      Grato. Muito legal seu template.

      Excluir
  10. Boa noite Andii, estou com uma dúvida, estou tomando como exemplo o seu código, estou tentando criar um link para o item do menu exatamente nessa parte

    só que a página quando abre não aparece o template, aparece em uma página em branco. Sendo que essa página eu copiei e colei do index. Pode me auxiliar?
    Obrigada

    ResponderExcluir
    Respostas
    1. Olá Andii, consegui resolver esse problema rsr
      estava no web.xml faltei trocar o *.xhtml
      quando troquei funcionou normalmente.
      :d

      Excluir
  11. Olá Andii Francisco Carlos legal seus postis você podia fazer um sisteminha de login cadastro e consulta exclusão e atualização com jsf 2.0 e hibernate e primefaces eu acho que fica muito legal.

    ResponderExcluir
    Respostas
    1. Olá Francisco! Isso que vc está pedindo tem no blog, separado em outros posts, por exemplo: http://javasemcafe.blogspot.com.br/p/nivel-iniciante.html aqui tem as postagens sobre o PrimeFaces, aqui sobre JPA (inclusive um crud) http://javasemcafe.blogspot.com.br/p/nivel-intermediario.html e por fim aqui tem a questão de segurança: http://javasemcafe.blogspot.com.br/p/nivel-avancado.html ... é só dar uma lida, juntar os posts que vc consegue fazer este crud :)

      Excluir
  12. Tem como disponibilizar o seu código Fonte no gitHub?

    ResponderExcluir
  13. Excelente post!
    Aplicou muito bem a engenharia de software, com poucas linhas de código, principalmente no tocante à manutenção e reuso de software... ao menos em meu projeto enxugou muitas páginas e me economizou várias linhas de código e de botões (CTRL C && CTRL V) xD

    ResponderExcluir
  14. Excelente post. Poderia me dizer qual a dimensão da imagem (top.jpg) ?

    ResponderExcluir
  15. boa tarde estou usando sua template, coloquei umas tabelas na parte do centro porem nao consigo abstrair os dados para o banco, oq ue seria ?

    ResponderExcluir

Deixe seu comentário... ;)