O que é o Facelets?
Segundo a especificação do Java EE 6:
"Facelets is a powerful but lightweight page declaration language that is used to build JavaServer Faces views using HTML style templates and to build component trees." Java EE 6
Traduzindo... Facelets é uma poderosa e leve linguagem de declaração de página que é usada para construir visualizações em JSF usando estilos de templates HTML e para construir árvores de componentes, que utiliza da tecnologia XHTML para a criação de páginas web.
O mais interessante e utilizado desta tecnologia é a possibilidade de criar templates para páginas JSF.
Agora vamos fazer alguns exemplos de utilização das 11 tags do Facelets, para isso crie um projeto JEE 6 (
Dessa forma), feito isso, vamos começar:
<ui:component >
Esta tag serve para criar componentes customizados em JSF.
Dentro do WEB-INF crie um diretório chamado componentes. Dentro deste diretório crie um arquivo xhtml com o nome meuComponente.xhtml que será nosso componente, segue o código:
<?xml version='1.0' encoding='UTF-8' ?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<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:component>
<h:form>
<h:inputText id="#{id}" value="#{value}" required="true" requiredMessage="Este campo obrigatório" />
<h:message for="#{id}" />
<h:commandButton value="Enviar" />
</h:form>
</ui:component>
</html>
Veja que no código acima usamos a tag ui:component, que define nosso componente, mas apenas isso não é suficiente para fazer ele funcionar, precisamos de um xml para mapear esse componente, então para isso crie um xml dentro do diretório componentes com o nome de
facelets.taglib.xml, nele teremos o seguinte código, que explicarei abaixo:
<?xml version="1.0"?>
<!DOCTYPE facelet-taglib PUBLIC "-//Sun Microsystems, Inc.//DTD Facelet Taglib 1.0//EN" "https://facelets.dev.java.net/source/browse/*checkout*/facelets/src/etc/facelet-taglib_1_0.dtd">
<facelet-taglib>
<namespace>http://javasemcafe.blogspot.com</namespace>
<tag>
<tag-name>componenteJSF</tag-name>
<source>meuComponente.xhtml</source>
</tag>
</facelet-taglib>
Bom... a tag
namespace pode ser preenchida por um link qualquer. A tag
tag-name será o nome pelo qual nosso componente será chamado, e a tag
source corresponde a localização do nosso componente em xhtml. Além de tudo isso precisamos registrar o xml criado dentro do
web.xml que está dentro do WEB-INF, logo após a tag
web-app insira o seguinte código:
<context-param>
<param-name>facelets.LIBRARIES</param-name>
<param-value>/WEB-INF/componentes/facelets.taglib.xml</param-value>
</context-param>
Agora sim podemos usar nosso componente, para isso, vamos usar a página index.xhtml criada por padrão ao criar o projeto, ela deverá ficar assim:
<?xml version='1.0' encoding='UTF-8' ?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml"
xmlns:h="http://java.sun.com/jsf/html"
xmlns:andii="http://javasemcafe.blogspot.com">
<h:head>
<title>Facelet Title</title>
</h:head>
<h:body>
<andii:componenteJSF id="meu" />
</h:body>
</html>
Veja que na tag html foi adicionado o namespace definido no
facelets.taglib.xml para assim podermos usar a tag
andii:componenteJSF .
Visualmente ele ficará dessa forma:
Bom.. quanto a essa tag do Facelets, acabei nem me aprofundando, apenas aprendi o básico para saber para o que ela servia.
<ui:debug >
Serve para abrir uma janela de debug quando pressionado as teclas: CTRL + SHIFT + a tecla definida na tag
ui:debug, para teste inclua essa tag na página index.xhtml, lembre-se de adicionar na tag html, o namespace para utilização do facelets, ficando dessa forma:
<html xmlns="http://www.w3.org/1999/xhtml"
xmlns:h="http://java.sun.com/jsf/html"
xmlns:andii="http://javasemcafe.blogspot.com"
xmlns:ui="http://java.sun.com/jsf/facelets">
E ainda no index.xhtml inclua dentro do h:body, a seguinte tag:
<ui:debug hotkey="K" />
Neste caso estamos usando a letra K para ser nossa hotkey, então para testar, abra no navegador a página index.jsf, a tag
ui:debug não ficará visível, apenas pressione CTRL+SHIFT+K, a seguinte tela deverá aparecer:
<ui:define > , <ui:insert > e <ui:composition >
Estas são as tags mais utilizadas quando se fala em Facelets, elas são para definir o template das páginas, como isso ocorre? a tag
ui:insert "demarca" onde será, por exemplo: o menu, o topo, o corpo do sistema. A
ui:define é utilizada nas páginas que desejam utilizar o template, então... um
ui:define é correspondente a um
ui:insert do template. E por fim, a
ui:composition serve para compor páginas que utilizam a tecnologia Facelets. Para testarmos isso vamos criar um template onde terá um menu vertical que ocupará 30% da página, e os outros 70% corresponderão ao corpo da página, para isso crie uma página JSF dentro de
Páginas Web, com o nome de template.xhtml, com o código:
<?xml version='1.0' encoding='UTF-8' ?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml"
xmlns:ui="http://java.sun.com/jsf/facelets"
xmlns:h="http://java.sun.com/jsf/html">
<h:head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
<title>Facelets Template</title>
<style type="text/css">
.styleMenu {
background-color: yellow;
width: 30%;
margin: 0; padding: 0;
float: left;
}
.styleCorpo {
background-color: red;
width: 70%;
float: right;
text-align: center;
}
</style>
</h:head>
<h:body>
<div class="styleMenu">
<ui:insert name="menu">menu original</ui:insert>
</div>
<div class="styleCorpo">
<ui:insert name="corpo">Corpo original do template</ui:insert>
</div>
</h:body>
</html>
No código acima veja que na realidade o menu e o corpo são demarcados por estilos de css nas div.
E para testar esse template, crie uma página JSF com o nome de
clienteTemplate.xhtml, que corresponderia a qualquer página que utilizaria um template, assim:
<?xml version='1.0' encoding='UTF-8' ?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml"
xmlns:ui="http://java.sun.com/jsf/facelets">
<ui:composition template="template.xhtml">
<ui:define name="corpo">
isso é do clienteTemplate
</ui:define>
</ui:composition>
</html>
O resultado será este:
Agora analise o código do
clienteTemplate.xhtml e veja que não foi criado um
ui:define para o menu, isso aconteceu porque eu não queria que o menu fosse sobrescrito, ou seja, eu quis utilizar o que tinha dentro do template que é o padrão, a menos que você sobrescreva ele terá outro resultado.
DICA: Para quem usa o NetBeans 6.9.1, ele já dá a opção de criar templates pré definidos, como fazer isso? Clique com o botão direito em
Páginas Web - Outro... selecione a categoria JavaServer Faces e use Modelo de Facelets para criar o template, aparecerá a seguinte tela:
Nela informe o nome para o template, e selecione o Estilo de layout, para selecionar basta clicar no layout escolhido, e clique em Finalizar...
Já para usar um template, faça os mesmos primeiros passos para criar o template, mas no lugar de escolher Modelo de Facelets, escolha
Cliente de modelo de facelets, e aparecerá a seguinte janela:
Nela informe um nome para a página, e lembre-se de selecionar o modelo de template que foi criado, eu geralmente prefiro usar a Marcação de raiz gerada como
ui:composition, pelo fato de estar usando Facelets mesmo.
Bom... agora tenha criatividade para criar/editar o template da forma que achar melhor :)
<ui:decorate >
Esta tem a mesma funcionalidade que a tag
ui:composition: serem utilizadas para fazer a composição de páginas que utilizam Facelets, com a diferença de que quando é utilizado a tag
ui:composition, o que estiver fora desta, não aparecerá na aplicação, ou seja será ignorada. Já ao usar a ui:decorate, o que for feito fora desta tag será visualizada normalmente, para testarmos isso, na página
clienteTemplate.xhtml que foi criada logo acima, depois da tag </ui:composition> e antes da </html>, escreva qualquer coisa, e mande atualizar a visualização, e veja que nada de diferente acontece... pois o que foi escrito fora da
ui:composition foi ignorado.
Agora para testar o
ui:decorate, nessa mesma página, troque o
ui:composition pelo
ui:decorate, salve e visualize o resultado, neste caso o que tinha sido escrito fora da tag, aparece normalmente no final da página. A imagem a seguir utiliza a tag
ui:decorate:
<ui:include > e <ui:fragment >
A tag
ui:include serve para incluir páginas dentro de outras páginas assim como o próprio include do PHP, por um exemplo, quando você ver que um código fonte de uma página vai ficar muito extenso, você pode separar ele em uma outra página, para a visualização isso não vai fazer diferença, pois na hora de renderizar ele irá renderizar como uma unica página, a diferença é que para dar manutenção em páginas não muito extensa é mais fácil. Já a tag
ui:fragment, não consegui entender muito bem a diferença em usar ela ou o
ui:composition, mas pelo o que andei lendo, o pessoal costuma usar ela nas páginas que forem incluídas pelo
ui:include, vamos fazer um exemplo usando essa combinação, primeiro crie uma página JSF que será a página a ser incluída, use o nome de
fragTeste.xhtml:
<?xml version='1.0' encoding='UTF-8' ?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<ui:fragment xmlns="http://www.w3.org/1999/xhtml"
xmlns:h="http://java.sun.com/jsf/html"
xmlns:ui="http://java.sun.com/jsf/facelets">
<h:outputText value="Essa texto é da página fragTeste" />
</ui:fragment>
Agora crie uma página JSF com o nome de
include.xhtml:
<?xml version='1.0' encoding='UTF-8' ?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml"
xmlns:h="http://java.sun.com/jsf/html"
xmlns:ui="http://java.sun.com/jsf/facelets"
xmlns:f="http://java.sun.com/jsf/core">
<h:head>
<title>Facelet Title</title>
<f:view contentType="text/html" />
</h:head>
<h:body>
<h:outputText value="Esse texto é da página include!" />
<br/>
<ui:include src="fragTeste.xhtml" />
</h:body>
</html>
O resultado da visualização da página
include.xhtml é o seguinte:
Obs:
Caso alguém saiba realmente o que a tag ui:fragment faz de diferente, ficaria grata se me informasse.
<ui:remove > e <ui:repeat >
A tag
ui:remove serve para remover um código que é inserido dentro dela, ou seja, o que for escrito entre ela não será visualizado (bom... não consigo enxergar a utilização dela na prática), crie uma página JSF com o nome de
remove.xhtml :
<?xml version='1.0' encoding='UTF-8' ?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml"
xmlns:h="http://java.sun.com/jsf/html"
xmlns:ui="http://java.sun.com/jsf/facelets">
<h:head>
<title>Facelet Title</title>
</h:head>
<h:body>
<h:outputText value="Isso aparece na minha pagina remove... pois está fora da tag ui:remove" />
<ui:remove>
<h:outputText value="Isso não aparece na minha página remove!!" />
</ui:remove>
</h:body>
</html>
A visualização será:
Já a tag
ui:repeat funciona praticamente como um laço de repetição para ler valores de uma lista de um bean, então... na raiz mesmo de
Pacotes de código-fonte, crie uma classe com o nome de
ClienteBean.java nessa classe teremos uma lista que será lida pela tag
ui:repeat. Segue o conteúdo da classe:
@Named
@javax.enterprise.context.RequestScoped
public class ClienteBean {
private List<String> clientes;
public ClienteBean() {
clientes = new ArrayList<String>();
clientes.add("Maria");
clientes.add("Joao");
clientes.add("Aparecida");
}
public List<String> getClientes() {
return clientes;
}
public void setClientes(List<String> clientes) {
this.clientes = clientes;
}
}
Agora crie uma nova página JSF, com o nome de
repeat.xhtml, segue:
<?xml version='1.0' encoding='UTF-8' ?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml"
xmlns:h="http://java.sun.com/jsf/html"
xmlns:ui="http://java.sun.com/jsf/facelets">
<h:head>
<title>Facelet Title</title>
</h:head>
<h:body>
<ui:repeat var="cli" value="#{clienteBean.clientes}">
<h:outputText value="#{cli}" /><br />
</ui:repeat>
</h:body>
</html>
Veja que essa tag tem seu funcionamento bem parecido com uma
h:dataTable, então não tem o que questionar dela. A visualização da mesma:
<ui:param >
A tag
ui:param serve para passar valores para outra página, esse valor pode ser estático ou dinâmico(vindo de um bean), não cheguei a usar essa tag em algum projeto, mas li que o pessoal usa ela bastante para passar o usuário logado de uma página para outra...
Vamos fazer um teste com um valor estático mesmo, primeiro crie uma página JSF, com o nome de
recebeParam.xhtml esta será a página que receberá o parâmetro vindo de uma outra página que irá chamá-la. O parâmetro a ser recebido nesse exemplo será o
nome:
<?xml version='1.0' encoding='UTF-8' ?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml"
xmlns:h="http://java.sun.com/jsf/html">
<h:head>
<title>Facelet Title</title>
</h:head>
<h:body>
<h:outputText value="Esta página estará recebendo um parâmetro vindo de uma outra página:" />
<br />
<h:outputText value="Parâmetro recebido: #{nome}" />
</h:body>
</html>
O parâmetro será capturado usando a EL #{nome}, então na página que chamará ela, precisa ser passado um parâmetro com o
name de
nome. Então agora crie uma nova página JSF com o nome de
enviaParam.xhtml:
<?xml version='1.0' encoding='UTF-8' ?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml"
xmlns:h="http://java.sun.com/jsf/html"
xmlns:ui="http://java.sun.com/jsf/facelets">
<h:head>
<title>Facelet Title</title>
</h:head>
<h:body>
<ui:param name="nome" value="andii.brunetta" />
<h:form>
<h:commandButton value="Chama a página recebeParam" action="recebeParam" />
</h:form>
</h:body>
</html>
Perceba que não é necessário que a tag
ui:param esteja dentro do
h:form, ou seja, ele não precisa de um form para ser encaminhado para a outra página, o form só está aí por causa do
h:commandButton.
Essa é a visualização da página acima:
Ao clicar no botão da página mostrada acima, esta chamará a
recebeParam.xhtml, que terá o seguinte resultado:
IMPORTANTE:
Caso você use o Google Chrome (indico usar ele!), ao testar alguns exemplos ele poderá dar um erro, a solução é acrescentar a seguinte tag dentro do h:head da página ou se estiver usando template, será no template mesmo:
<f:view contentType="text/html" />
Para mais informações acesse a documentação do Facelets:
Tag Library Documentation - Facelets
Bom até que enfim finalizamos essa postagem... esta ficou bemmmmm extensa, mas está completa com as todas as tags do Facelets! Caso alguém tenha mais informações sobre elas, pode complementar a postagem comentando abaixo! ;)