• Skip to primary navigation
  • Skip to content

Mauda

IT, Java and Music

Graduação   SCJP   Mestrado
  • Apresentação
  • Certificação Java
  • JPA
    • Exceptions
  • JSF
  • Versionamento
  • Contato

Erros JSF – PrimeFaces – p:dataTable não aparece após update Ajax

November 30, 2015 by Mauda Leave a Comment

Conteúdo do Post:
  1. Contexto do Problema – Documentação
  2. Código da Solução – Versão Inicial
  3. Rodando o código da Versão Inicial… e ERRO!
  4. Relembrando… DOM Tree
  5. Código da Solução – Versão Final
  6. finnaly{

Olá Pessoal, tudo bom?

No artigo de hoje iremos descrever um erro que ocorre quando combinamos Ajax com o Atributo rendered de um panel, dataTable ou qualquer outro componente que possua esse atributo. O desenvolvedor faz tudo “corretamente”, mas o componente desejado não aparece na tela e o pior não aparece nenhum erro no console do Eclipse. O que fazer então?

Contexto do Problema – Documentação

Observe as telas representadas nas Figuras 01 e 02. A Figura 01 representa um “filtro” de pesquisa, o qual possui um botão Pesquisar, que, de acordo com a Figura 02, irá mostrar um Data Table com as informações de cada Herói.

Figura 01 – Filtro de pesquisa com o botão Pesquisar

 

Figura 02 – Data Table com as informações dos Heróis

Dessa forma o desenvolvedor irá desenvolver um código que crie uma tela que tenha esse padrão, um filtro de pesquisa, um botão que realiza uma ação de trazer dados de uma camada Business e que apresenta esses dados em uma data table na tela.

Código da Solução – Versão Inicial

Primeira observação: O código mostrado aqui é a titulo de compreensão do erro. Você não irá criar um filtro de pesquisa sem campos, ou uma busca que traz resultados estáticos. Aqui é apenas para demonstrar o erro. Dito isso vamos para os códigos.

Para atender a documentação descrita acima, o desenvolvedor gera o código para a página testeDataTableNaoAparece.xhtml:

Codigo 01 - Pagina testeDataTableNaoAparece.xhtml
Java
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
<!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:f="http://java.sun.com/jsf/core"
xmlns:h="http://java.sun.com/jsf/html"
xmlns:p="http://primefaces.org/ui">
 
<h:head>
<title>Vingadores</title>
</h:head>
<h:body>
<h:form>
<p:panel>
<f:facet name="header">
Teste DataTable Que Não Aparece
</f:facet>
<p:commandButton value="Pesquisar"
action="#{testeDataTableNaoApareceMB.pesquisar}"
update="resultados" />
</p:panel>
<p:dataTable value="#{testeDataTableNaoApareceMB.vingadores}" var="vingador"
rendered="#{not empty testeDataTableNaoApareceMB.vingadores}"
rowKey="#{vingador.id}"
id="resultados" >
<f:facet name="header">
Vingadores
</f:facet>
<p:column headerText="Heroi">
#{vingador}
</p:column>
</p:dataTable>
</h:form>
</h:body>
</html>

Repare que o componente p:dataTable, possui preenchido o atributo rendered, onde somente com a lista com informações será exibida em tela e possui também um id, resultados, que é chamado pelo atributo update do componente p:commandButton.

Além disso o desenvolvedor fez o Managed Bean TesteDataTableNaoApareceMB:

Java
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
package br.com.mauda.view.mb;
 
import java.io.Serializable;
import java.util.ArrayList;
import java.util.Collection;
 
import javax.annotation.PostConstruct;
import javax.faces.bean.ManagedBean;
 
@ManagedBean
public class TesteDataTableNaoApareceMB implements Serializable{
/////////////////////////////////////
// Atributos
/////////////////////////////////////
private static final long serialVersionUID = 1L;
private Collection<String> vingadores;
/////////////////////////////////////
// Construtores
/////////////////////////////////////
public TesteDataTableNaoApareceMB() {
}
@PostConstruct
private void init(){
vingadores = new ArrayList<String>();
}
/////////////////////////////////////
// Actions
/////////////////////////////////////
//Action de Pesquisar a partir do filtro
public void pesquisar() {
if(vingadores.isEmpty()){
vingadores.add("Hulk");
vingadores.add("Capitão América");
vingadores.add("Homem de Ferro");
vingadores.add("Thor");
vingadores.add("Viuva Negra");
vingadores.add("Gavião Arqueiro");
}
}
/////////////////////////////////////
// Getters and Setters
/////////////////////////////////////
public Collection<String> getVingadores() {
return vingadores;
}
}

Esse Managed Bean é bem simples, com a ressalva que o método pesquisar() está inserindo valores estaticamente. Isso não deve ocorrer em um código do mundo real 🙂

Rodando o código da Versão Inicial… e ERRO!

Rode o projeto JSF e acesse a página construída. O sistema irá exibir a tela com o filtro. Agora clique no botão Pesquisar. Não irá aparecer o DataTable… Olhe no console do Eclipse e aí alguma coisa? Nada… Pô! que droga! o Código está correto! (Pelo menos na sua visão :-))

Relembrando… DOM Tree

Para contextualizar vamos lembrar um pouco sobre DOM tree a partir desse artigo. Agora com essa explanação vamos pensar no código da página xhtml. Repare no seguinte trecho:

Java
1
2
3
4
<p:dataTable value="#{testeDataTableNaoApareceMB.vingadores}" var="vingador"
rendered="#{not empty testeDataTableNaoApareceMB.vingadores}"
rowKey="#{vingador.id}"
id="resultados" >

Observe o que faz a linha 2. O atributo rendered deste componente somente o renderiza se ele for verdadeiro. Vamos pensar no primeiro momento da página, quando realizamos o acesso a esta. Esse componente p:dataTable NÃO SERÁ RENDERIZADO, pois não existe nenhum elemento dentro da collection vingadores. Agora juntando essa informação com a informação sobre DOM Tree, temos que no primeiro acesso a página não existirá um nodo para o p:dataTable.

Como dentro do componente p:commandButton, temos a parte de re renderização (update) de uma requisição Ajax apontando para o ID do componente p:dataTable, temos a seguinte pergunta: Qual ID essa requisição Ajax irá atualizar? Pense que esse ID não existe na Arvore DOM do documento HTML. Toda requisição Ajax utiliza o metodo JavaScript document.getElementById(). Assim se o ID não está descrito na Arvore DOM, logo esse método não recuperará o Element, ocasionando o Erro.

Lógico não descarto aqui que deveria ser informado, ao menos no console da IDE, que o JSF não identificou determinado ID. Isso auxiliaria a encontrar o erro.

Código da Solução – Versão Final

Para solucionar esse erro, nós devemos ter um componente que já esteja renderizado no DOM Tree já no primeiro acesso a página. Uma forma simples de realizar isso é criar um panel que englobe toda a região de desejamos re renderizar. Dessa forma a linha 23 cria um p:panel que contém o ID que iremos colocar no update e, para não causar erros de ids duplicados, removemos o id que estava dentro do componente p:dataTable. O style css adicionado ao p:panel é apenas para que não seja renderizada uma borda de cor preta na tela. Veja a solução completa no código abaixo, as linhas destacadas são as que foram acrescidas:

Java
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
<!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:f="http://java.sun.com/jsf/core"
xmlns:h="http://java.sun.com/jsf/html"
xmlns:p="http://primefaces.org/ui">
 
<h:head>
<title>Vingadores</title>
</h:head>
<h:body>
<h:form>
<p:panel>
<f:facet name="header">
Teste DataTable Que Não Aparece
</f:facet>
<p:commandButton value="Pesquisar"
action="#{testeDataTableNaoApareceMB.pesquisar}"
update="resultados" />
</p:panel>
<p:panel id="resultados" style="border:0px;">
<p:dataTable value="#{testeDataTableNaoApareceMB.vingadores}" var="vingador"
rendered="#{not empty testeDataTableNaoApareceMB.vingadores}"
rowKey="#{vingador.id}">
<f:facet name="header">
Vingadores
</f:facet>
<p:column headerText="Heroi">
#{vingador}
</p:column>
</p:dataTable>
</p:panel>
</h:form>
</h:body>
</html>

Com esse código ao clicar no botão Pesquisar, a Data Table desejada será renderizada em tela.

finnaly{

Uma observação aqui que se faz necessária, é que esse erro ocorre devido a combinação Ajax + rendered. Assim não importa se você está renderizando um data table ou panel ou até mesmo um botão. Caso este não esteja presente na DOM tree, o JSF não conseguirá realizar a renderização. Pense também em soluções alternativas como utilizar o disabled, pois nesse caso o componente já estaria na DOM tree, mas desabilitado em tela. Isso pode ajudar a evitar esses problemas.

Duvidas ou sugestões? Deixe seu feedback! Isso ajuda a saber a sua opinião sobre os artigos e melhorá-los para o futuro! Isso é muito importante!

Até um próximo post!

Filed Under: JSF Tagged With: Ajax, JSF, p:commandButton, p:dataTable, PrimeFaces, update

About Mauda

Mestre em Informática, Analista de Sistemas, Professor, SCJP e Baterista. Desde 2002 trabalhando no mundo Java e ensinando pessoas sobre desenvolvimento de sistemas. Mais informações

Reader Interactions

Leave a Reply Cancel reply

Your email address will not be published. Required fields are marked *

This site uses Akismet to reduce spam. Learn how your comment data is processed.

Advertisements

Copyright © 2025 · Genesis Framework · WordPress · Log in