Aula 13: JSF (III)
Diego Passos
Universidade Federal Fluminense
T´ecnicas de Projeto e Implementac¸˜ao de Sistemas II
Aula Passada
JSF Actions e Views.
Regras de Navegac¸˜ao.
Componentes mais sofisticados.
Eventos da interface com o usu´ario.
Nesta Aula
Construc¸˜ao de tabelas.
Validac¸˜ao de dados.
Mensagens.
Construc¸˜ ao de Tabelas
JSF cont´em componentes que permitem a criac¸˜ao de tabelas em views.
Estas tabelas podem ser classificadas em dois grupos:
I Tabelas de componentes.
F Permitem agrupar e organizar outros componentes JSF.
F N´umero de componentes deve ser conhecido em tempo de desenvolvimento.
I Tabelas de dados.
F Permitem exibir conjuntos de dados.
F Permitem iterar por listas, por exemplo.
F Se adaptam a quantidades arbitr´arias de dados, definidas em tempo de execuc¸˜ao.
Tabelas de Componentes: A Tag panelGrid
Tabelas de componentes s˜ao implementadas com a tagpanelGrid. Exemplo:
<h:panelGridcolumnClasses="rowLabel,rowContent"columns="2">
<h:outputTextvalue="Title:"/>
<h:outputTextvalue="#{bookdisplayform.book.title}"/>
<h:outputTextvalue="Author:"/>
<h:outputTextvalue="#{bookdisplayform.book.author}"/>
<h:outputTextvalue="ISBN:"/>
<h:outputTextvalue="#{bookdisplayform.book.ISBN}"/>
<h:outputTextvalue="Status:"/>
<h:outputTextvalue="#{bookdisplayform.book.checkedOut ? ’Checked Out’ : ’Checked In’}"/>
</h:panelGrid>
Devemos especificar um n´umero de colunas desejado.
N´umero de linhas ´e implicitamente calculado com base no n´umero de componentes da tabela.
Tabelas de Componentes: A Tag panelGrid (II)
A tag aceita tamb´em especificac¸˜oes de CSS.
No exemplo anterior, foram especificados estilos diferentes para cada coluna:
<h:panelGridcolumnClasses="rowLabel,rowContent"columns="2">
Classes rowLabel e rowContentfazem referˆencia a estilos definidos em um CSS:
.rowLabel{
background-color: #dddddd;
padding-left: 1em;
padding-right: 1em;
padding-top: 0.2em;
padding-bottom: 0.2em;
text-align:right;
border:thin solid#000000;
}
.rowContent{ padding-left: 1em;
padding-right: 1em;
padding-top: 0.2em;
padding-bottom: 0.2em;
text-align:right;
border:thin solid#000000;
Tabelas de Componentes: A Tag panelGrid (III)
Pode-se especificar CSS para:
I Colunas.
I Linhas.
I Cabec¸alho.
I Rodap´e.
Outro exemplo (com linhas):
<h:panelGridrowClasses="oddRows,evenRows"columns="4">
<!-- Especificac¸˜ao dos Componentes. -->
</h:panelGrid>
Especificac¸˜ao diz que a primeira linha ´e da class oddRows. Segunda linha ´e da classeevenRows.
Se h´a mais de duas linhas, padr˜ao se repete ciclicamente.
Tabelas de Componentes: A Tag panelGrid (IV)
Note que a tag s´o afeta componentes de interface.
Considere o seguinte trecho de c´odigo:
<h:panelGridrowClasses="oddRows,evenRows"columns="4">
Algum texto solto.
<ahref="teste.html">Um Link</a>
<h2>Um header</h2>
</h:panelGrid>
O que ocorre neste caso?
Grupos de Componentes: A Tag panelGroup
Uma tag relacionada `a tag panelGrid´e apanelGroup. Esta tag agrupa v´arios componentes em uma mesma unidade.
I Como se fossem um ´unico componente.
Pode ser usado para simplificar a decis˜ao de renderizac¸˜ao de um grupo de componentes.
Ou para organiz´a-los em um panelGrid.
Grupos de Componentes: A Tag panelGroup (II)
Exemplo 1: agrupamento para renderizac¸˜ao.
<h:panelGrouprendered="#{bookdisplayform.bookSelected}">
<h:panelGridcolumnClasses="rowLabel,rowContent"columns="2">
<h:outputTextvalue="Title:"/>
<h:outputTextvalue="#{bookdisplayform.book.title}"/>
<h:outputTextvalue="Author:"/>
<h:outputTextvalue="#{bookdisplayform.book.author}"/>
<h:outputTextvalue="ISBN:"/>
<h:outputTextvalue="#{bookdisplayform.book.ISBN}"/>
<h:outputTextvalue="Status:"/>
<h:outputText
value="#{bookdisplayform.book.checkedOut ? ’Checked Out’ : ’Checked In’}"/>
</h:panelGrid>
<h:panelGroupid="buttonHolder">
<h:panelGrouprendered="#{usersession.currentUser.borrower}">
<h:commandButtonvalue="Check Out"action="#{bookdisplayform.checkBookOut}"
rendered="#{not bookdisplayform.book.checkedOut}"/>
</h:panelGroup>
<h:panelGrouprendered="#{usersession.currentUser.librarian}">
<h:commandButtonvalue="Check In"action="#{bookdisplayform.checkBookIn}"
rendered="#{bookdisplayform.book.checkedOut}"/>
</h:panelGroup>
</h:panelGroup>
</h:panelGroup>
Grupos de Componentes: A Tag panelGroup (III)
Exemplo 2: agrupamento de componentes em c´elulas de colunas.
<h:panelGridcolumnClasses="rowLabel,rowContent"columns="2">
<h:panelGroup>
<h:outputTextvalue="Title:"/><br>
<h:outputTextvalue="Author:"/><br>
<h:outputTextvalue="ISBN:"/><br>
<h:outputTextvalue="Status:"/>
</h:panelGroup>
<h:panelGroup>
<h:outputTextvalue="#{bookdisplayform.book.title}"/><br>
<h:outputTextvalue="#{bookdisplayform.book.author}"/><br>
<h:outputTextvalue="#{bookdisplayform.book.ISBN}"/><br>
<h:outputText
value="#{bookdisplayform.book.checkedOut ? ’Checked Out’ : ’Checked In’}"/>
</h:panelGroup>
</h:panelGrid>
Tabelas de Dados
As tabelas geradas pelo componentepanelGrid podem conter dados e valores dinˆamicos.
Mas s˜ao est´aticas em formato.
I N´umero de c´elulas (linhas e colunas) ´e fixo.
I Definido em tempo de codificac¸˜ao.
Mas em geral, queremos permitir tabelas de dados com n´umero de linhas vari´avel.
I Definido em tempo de execuc¸˜ao.
Exemplo: resultado de uma consulta SQL.
Tabelas de Dados: As Tags dataTable e column
A tag dataTable permite a definic¸˜ao de tabelas de dados com n´umero de linhas definido em tempo de execuc¸˜ao.
Ela funciona como umfor, iterando por elementos de uma colec¸˜ao.
Cada iterac¸˜ao corresponde a uma linha da tabela gerada.
Ela pode recebe como atributos:
I Um valor, indicando de onde obter a colec¸˜ao a ser iterada.
I Um nome de vari´avel tempor´aria que receber´a cada elemento da colec¸˜ao.
Tabelas de Dados: As Tags dataTable e column (II)
Exemplo:
<h:dataTablevalue="#{library.bookList}"headerClass="tableHeader"var="book">
<h:column>
<f:facetname="header">
<h:outputTextvalue="Title"/>
</f:facet>
<h:outputTextvalue="#{book.title}"/>
</h:column>
<h:column>
<f:facetname="header">
<h:outputTextvalue="Author"/>
</f:facet>
<h:outputTextvalue="#{book.author}"/>
</h:column>
<h:column>
<f:facetname="header">
<h:outputTextvalue="Checked Out"/>
</f:facet>
<h:selectBooleanCheckboxonclick="submit()"
value="#{book.checkedOut}"/>
</h:column>
</h:dataTable>
O corpo da tagdataTablecont´em tags columnque definem o conte´udo de cada coluna.
Em geral, conte´udo de uma coluna ´e obtido a partir da vari´avel tempor´aria da iterac¸˜ao.
Tabelas de Dados: As Tags dataTable e column (II)
Resultado:
Library Administration
Return Home
Title Author Checked Out
J2EE Design Patterns William Crawford & Jonathan Kaplan Moby Dick Herman Melville
Tabelas de Dados e Valores Edit´ aveis
Note que campos da tabela de dados podem ser edit´aveis.
I No exemplo anterior, h´a umcheckbox associado a um atributo booleano do livro (emprestado ou n˜ao).
O usu´ario ´e livre para fazer modificac¸˜oes.
Estas modificac¸˜oes s˜ao automaticamente traduzidas para mudanc¸as nos atributos dos objetos.
Validac¸˜ ao de Dados
Quase todosoftware permite e requer que o usu´ario fornec¸a dados de entrada.
Muitas vezes, no entanto, o software precisa verificar se a entrada ´e v´alida.
Uma entrada pode ser inv´alida por v´arias raz˜oes:
I O formato pode ser inv´alido.
I Pode haver restric¸˜oes em relac¸˜ao `as faixas de valor.
I Pode haver restric¸˜oes em relac¸˜ao a utilizar dois campos de um mesmo formul´ario simultaneamente.
I . . .
Validac¸˜ ao de Dados (II)
JSF provˆe suporte a validac¸˜ao de dados para todos os componentes.
A validac¸˜ao pode utilizar validadores padr˜ao ou validadores personalizados.
Suponha uma view que permita a adic¸˜ao de novos livros na biblioteca.
O cadastro de um livro precisa de trˆes campos (neste exemplo simplificado):
I T´ıtulo: n˜ao pode ser menor que 5 caracteres.
I Autor.
I ISBN: tem um formato padronizado.
Adicionalmente, todos os trˆes campos s˜ao necess´arios.
Validac¸˜ ao de Dados (III)
Exemplo (JSP):
<table>
<tr>
<td>Title:</td>
<td><h:inputTextid="title" binding="#{addbookform.title}"
required="true">
<f:validateLengthminimum="5"/>
</h:inputText>
<h:messagestyleClass="validationWarning" for="title"/>
</td>
</tr>
<tr>
<td>Author:</td>
<td><h:inputTextid="author"binding="#{addbookform.author}"
required="true"/>
<h:messagestyleClass="validationWarning" for="author"/>
</td>
</tr>
<tr>
<td>ISBN:</td>
<td><h:inputTextid="isbn"binding="#{addbookform.isbn}"
required="true">
<f:validator
validatorId="ISBNValidator"/>
</h:inputText>
<h:messagestyleClass="validationWarning" for="isbn"/>
</td>
Validac¸˜ ao de Dados (IV)
Quando o formul´ario ´e submetido, oFacesServlet executa todos os validadores da p´agina.
Validadores s˜ao executados para cada componente.
I Se o processo de validac¸˜ao falha, mensagens s˜ao adicionadas `afila de mensagensda p´agina.
Todos os validadores s˜ao checados, independente do sucesso ou falha dos anteriores.
Em caso de um ou mais erros de validac¸˜ao, aview original ´e exibida novamente para o usu´ario.
I Contendo as mensagens de erro.
Validadores Padr˜ ao
H´a v´arias tags que proveˆem validadores padronizados do JSF.
Estes validadores fazem checagens comuns nos dados entrada.
Exemplo:
<h:inputTextid="title"binding="#{addbookform.title}"required="true">
<f:validateLengthminimum="5"/>
</h:inputText>
Tag validateLength: determina tamanhos m´ınimo e m´aximo para o valor de entrada.
Validadores Padr˜ ao (II)
Segundo exemplo:
<h:inputTextlabel="Amount"id="withdraw"value="#{accountBean.withdrawAmount}">
<f:validateLongRangeminimum="20"maximum="1000"/>
</h:inputText>
Tag validateLongRange: determina que entrada tem que ser inteiro e entre valores m´ınimo e m´aximo.
Validadores Padr˜ ao (III)
Terceiro exemplo:
<h:inputTextid="withdraw"value="#{accountBean.withdraw.amount}">
<f:validateDoubleRangeminimum="20.00"maximum="1000.00"/>
</h:inputText>
Tag validateDoubleRange: entrada pode ser ponto flutuante, mas entre valores m´ınimo e m´aximo.
Validadores Padr˜ ao (IV)
E poss´ıvel tamb´´ em garantir a existˆencia de um valor.
I i.e., forc¸ar o usu´ario a fornecer o dado.
Componentes de entrada de dados cont´em um atributorequired.
I Quandotrue, validador ´e executado verificando se campo foi preenchido.
Exemplo:
<h:inputTextid="title"binding="#{addbookform.title}"required="true">
<f:validateLengthminimum="5"/>
</h:inputText>
Note que mais de um validador pode ser adicionado a um mesmo componente.
Mensagens de Erro de Validac¸˜ ao
Como exatamente as mensagens de erro de validac¸˜ao s˜ao exibidas para o usu´ario?
JSF fornece tags especiais para a exibic¸˜ao destas mensagens.
Especificamente, h´a duas tags ligeiramente diferentes:
I A tagh:messages.
I E a tagh:message.
A primeira exibe todasas mensagens de erro produzidas ao processar uma p´agina.
I Vimos um exemplo naview de login.
A segunda permite a exibic¸˜ao de mensagens espec´ıficas.
Mensagens de Erro de Validac¸˜ ao (II)
No caso dos validadores, as mensagens de erro est˜ao associadas a determinados componentes.
A tag h:message permite que filtremos mensagens por componente.
Exemplo:
<td>Title:</td>
<td><h:inputTextid="title" binding="#{addbookform.title}"required="true">
<f:validateLengthminimum="5"/>
</h:inputText>
<h:messagestyleClass="validationWarning" for="title"/>
</td>
Esta ocorrˆencia da tag exibe mensagens apenas para o componente associado ao t´ıtulo.
I N˜ao por estar dentro do corpo do componente, mas pelo nome especificado no atributo for.
Validadores Personalizados
Em alguns casos, os validadores providos pelo JSF n˜ao s˜ao suficientes.
Exemplo: como validar se o ISBN provido pelo usu´ario ´e v´alido?
Nestes casos, precisamos escrever nossos pr´oprios validadores.
Para isto, basta escrevermos uma classe Java que estende a interface javax.faces.validator.Validator.
Validadores Personalizados (II)
Exemplo (Java)
importjavax.faces.application.FacesMessage;
importjavax.faces.component.UIComponent;
importjavax.faces.context.FacesContext;
importjavax.faces.validator.Validator;
importjavax.faces.validator.ValidatorException;
public classISBNValidatorimplementsValidator{ publicvoidvalidate(FacesContext facesContext,
UIComponent uiComponent,Object o) throwsValidatorException{ String val=o.toString();
if(val!=null) {
if (val.length() == 10) { if(!checkISBN(val))
throwValidatorException("ISBN does not pass "+
"validation");
}else{
throwValidatorException("ISBN must be 10 "+
"characters");
} } }
privatebooleancheckISBN(String ISBN) { intsum= 0;
for(inti= 0;i< 10;i++) { charcurrent=ISBN.charAt(i);
intnum= 0;
if(current==’X’) num= 10;
else
num=current;
sum+= (num* (10-i));
}
return(sum% 11 == 0);
}
privatevoidthrowValidatorException(String detail) throwsValidatorException{
FacesMessage message=newFacesMessage();
message.setSeverity(FacesMessage.SEVERITY_ERROR);
message.setSummary("Invalid ISBN");
message.setDetail(detail);
throw newValidatorException(message);
} }
Validador gera uma excec¸˜ao em caso de falha de validac¸˜ao.
Validadores Personalizados (III)
Antes de utilizar um validador personalizado, devemos declar´a-lo no faces-config.xml:
<validator>
<validator-id>ISBNValidator</validator-id>
<validator-class>com.oreilly.jent.jsf.library.validator.ISBNValidator</validator-class>
</validator>
Validadores Personalizados (IV)
Finalmente, no JSP podemos usar a tag validator:
<f:validatorvalidatorId="ISBNValidator">