Dicas para trabalhar com sua DataTable usando RichFaces
Postado em 10. mai, 2011 por Raphael Lacerda and Geraldo Ferraz em Java
Se você trabalha com JSF, já deve ter trabalhado com algumas das várias bibliotecas de componentes, seja com RichFaces, PrimeFaces, IceFaces ou ainda outra. Para nossa escolha, levamos em consideração fatores como: variedade de componentes, facilidade de customização, documentação e principalmente, se possui os componentes necessários para resolver o problema específico da aplicação.
A MundoJ edição 44 comparou vários dos principais componentes dessas bibliotecas, mostrando as vantagens e desvantagens de cada uma. Especificamente no RichFaces, podemos utilizar o componente <rich:dataTable/>, que é simples de ser usado e atende muitos casos, sendo uma boa evolução em relação à dataTable padrão.
Com ele podemos filtrar usando os atributos filterBy e filterEvent ou ordenar as informações por alguma coluna usando o atributo sortBy. Também é possível fazer um agrupamento de linhas e colunas (colspan e rowspan) usando as tags rich:columnGroup assim como fazer uso de sub tabelas usando a tag rich:subTable como no exemplo abaixo:
<rich:columnGroup>
<rich:column rowspan="2">
<rich:spacer />
</rich:column>
<rich:column colspan="3">
<rich:spacer />
</rich:column>
<rich:subTable var="" value="">
<rich:column>
<rich:spacer/>
</rich:column>
</rich:subTable>
</rich:columnGroup>

Quando precisamos de algo mais sofisticado, como selecionar uma linha, reordenar as colunas ou até mesmo agrupar as informações, temos que trocar o dataTable por um componente mais poderoso, o ExtendedDataTable. Esse componente é muito semelhante ao primeiro e vai além, permitindo modificações extras feitas diretamente pelo usuário, tornando a experiência mais agradável e flexível, podendo analisar as informações de uma perspectiva diferenciada. Para selecionar uma linha usamos o atributo selection e se precisarmos selecionar varias linhas alteramos o atributo selecionMode (multi, single e none). Se quisermos agrupar as linhas a partir dos valores de uma determinada coluna usamos o atributo groupingColumn.

Navegando pelo sistema, o cliente perceberá que ao voltar para a tela de listagem, todas as modificações feitas na tabela foram perdidas, como é habitual na web. O ExtendedDataTable por padrão, não guarda as customizações feitas pelo usuário. Todavia, ele possui um mecanismo para manter o estado da tabela através da propriedade tableState. Essa propriedade guarda uma configuração em uma String com o estado da tabela para que possamos armazená-lo.
<rich:extendedDataTable tableState="#{preferenciaController.preferencia}"/>
Basta fazer um binding com um ManagedBean em uma String. Para que a solução seja válida, precisamos que o escopo desse Bean seja no mínimo de Session, para manter as configurações durante todo o tempo em que o usuário estiver usando o sistema:
@ManagedBean(name="preferenciaController")
@SessionScoped
public class PreferenciaController {
private String preferencia;
public String getPreferencia() {
return preferencia;
}
public void setPreferencia(String preferencia) {
this.preferencia = preferencia;
}
}
A String preferencia será populada com um JSON que contém toda a configuração do estado atual da tabela, como por exemplo o abaixo:
{
"columnsVisibility":{
"categoria":"1","numeroSolicitacao":"1","situacao":"1"
},
"columnGroupingState":{
"order":"ASCENDING","columnId":"numeroSolicitacao"
},
"columnsSizeState":{
"categoria":"100","numeroSolicitacao":"100","situacao":"28",
},
"columnsOrder":["numeroSolicitacao","categoria","situacao"]
}
Contudo, solucionamos parcialmente o problema, pois se o usuário sair do sistema, a sessão expirar ou entrar em outro navegador, perderemos toda a informação que estava no JSON. Para resolvermos definitivamente, podemos persistí-lo em um banco de dados, assim, quando ele voltar ao sistema, basta carregar a informação novamente:
@Entity
public class PreferenciaUsuario {
private String preferencia;
@Column(length=3500)
public String getPreferencia() {
return preferencia;
}
public void setPreferencia(String preferencia) {
this.preferencia = preferencia;
}
}
Ao começar a utilizar esse recurso, você notará que para cada modificação feita em seu componente, uma requisição Ajax será disparada para atualizar o valor em seu ManagedBean. Aqui há um problema, pois um update pode ser disparado a cada uma dessas requisições ajax, se as preferências carregadas previamente estiverem ainda gerenciadas (managed) pelo seu EntityManager, seja porque o seu ManagedBean está em um escopo de Conversation ou o @PersistenceContext(type=PersistenceContextType.EXTENDED) foi utilizado.
Existem algumas formas de solucionar, uma delas é após carregar o objeto de Preferências do usuário, colocá-lo no estado detached e na hora de salvar fazer merge. Uma outra forma, caso esteja utilizando o Seam, é controlar manualmente o flush da transação. Ou até mesmo oferecer uma forma explícita do usuário escolher quando gravar o estado da tabela.

Tabelas e listagens são frequentes numa aplicação web, e parece que o cliente nunca está satisfeito: sempre quer um filtro a mais, uma coluna a menos, uma ordenação aqui e ali. Os datatables dos diversos vendors de JSF possibilitam realizar esse trabalho com facilidade, e cada um vai oferecer opções específicas e bastante elaboradas. Conhece-las irá poupá-lo de muito trabalho.
ASSINE NOSSO RSS




Alberto
10. mai, 2011
Muito boa a dica, atualmente gravo o estado da tabela no cookie…
Lazaro
10. mai, 2011
Muito util a dica. Vou tentar fazer essa parada de selecionar várias linhas
Orélio Antônio Saraiva
10. mai, 2011
Raphael,
Parabéns !!!! Fico contente de você manter um nível profissional com visão de inovação e entrega de resultado. Muito sucesso sempre !!! Gostei das dicas e vou divulgar.
Danilo Miranda
10. mai, 2011
@Raphael
Muito bom o post! Abre os nossos horizontes para a utilização dos componentes do RichFaces.
Grande abraço,
Rafael Ponte
10. mai, 2011
Excelente post, Raphael.
Post simples, objetivo e o melhor, absolutamente útil! Espero ver mais posts sobre JSF e afins no blog da Caelum.
Um abraço e parabéns!
Raphael Lacerda
11. mai, 2011
@rponte
deve sair um de seam3… hehehe
Dausther
11. mai, 2011
Raphael,
Parabéns pelo post! Sucesso na carreira!
Abraço!
Hugo Santos
11. mai, 2011
Muito bom e útil o post obrigado.
Aliás o link “MundoJ edição 44″ está “quebrado”
Raphael Lacerda
11. mai, 2011
@Hugo
Tnks very much! Vou consertar!
http://mundoj.com.br/44conteudo.shtml
Felipe Z. Affonso
12. mai, 2011
Incrível esse post. Era exatamente o que eu estava precisando! A Caelum além de estar sempre inovando, agora deu pra adivinhar o que estamos precisando naquele exato momento.
DEMAIS!
Muito obrigado.
Alexandre Seabra
13. mai, 2011
Post muito maneiro, objetivo e com muitas informações úteis.
Parabéns.
Renata
13. jul, 2011
Eu preciso muito da ajuda de alguém pra isso, como eu faço pra minha tabela ter linhas que expandem em outras linhas? e como eu faço pra fazer o upload de uma música e depois de colocar ela no banco de dados, poder mostrar e ouvir ela através desta tabela? O objetivo é um programa web que tenha as músicas disponíveis para ouvir, depois que alguém carregou elas do computador.
Giovanni Machado
04. out, 2011
Hahahaha !!! Tive que postar este comentário. Eu estava lendo atentamente o artigo e “tals”, quando, ao ver o screenshot do exemplo, pensei “eu já vi essa tela antes”. Só então fui ver quem era o autor. Graaaande Raphael !!! Parabéns pelo artigo.
Abrasssssss
Giovanni
Alexandre
05. jan, 2012
Gostaria de saber se tem como o JSON pegar exatamente as linhas e colunas como se fosse o espelho da tabela, pois ao exportar para o excel ele exporta com a configuração que vem do banco não com a configuração de visualização da tabela.