Olá, estou com uma página .xhtml que possui alguns forms e dataTables. A tabela de listagem de livros cadastrados está apresentando um problema estranho. Quando cadastro algum livro o footer da tabela é atualizado, mas a tabela em si não, tanto que nem chega a acrescentar um botão de paginação quando cadastro mais que 10 livros por exemplo (estou paginando com 5 itens na tabela). O mesmo acontece quando tento excluir um livro. O footer com o tamanho da lista de livros no bean é atualizado mas a tabela em si não. Somente com um refresh na página.
A tabela com problemas fica abaixo do comentário "" com id="tabelaLivros"
Código completo do 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://xmlns.jcp.org/jsf/html"
xmlns:f="http://xmlns.jcp.org/jsf/core"
xmlns:ui="http://xmlns.jcp.org/jsf/facelets"
xmlns:p="http://primefaces.org/ui"
xmlns:fn="http://java.sun.com/jsp/jstl/functions">
<h:head />
<ui:composition template="_template.xhtml">
<f:metadata>
<f:viewParam name="livroId" value="#{livroBean.livro.id}" id="livroId"/>
<f:viewAction action="#{livroBean.carregaLivroPorId}" if="#{param.livroId != null}"/>
</f:metadata>
<ui:define name="titulo">Livros</ui:define>
<ui:define name="conteudo">
<h:form id="formCamposLivro">
<!-- CAMPOS DO LIVRO -->
<p:fieldset legend="Novo Livro" toggleable="true">
<p:panel header="Dados do Livro">
<h:panelGrid columns="2">
<p:outputLabel value="Titulo:" for="titulo" />
<p:inputText id="titulo" value="#{livroBean.livro.titulo}"
required="true" requiredMessage="Título obrigatório."
validatorMessage="O título não deve possuir tamanho superior a 40 caracteres." styleClass="formLivro">
<f:validateLength maximum="40" />
<f:ajax event="blur" />
</p:inputText>
<p:outputLabel value="ISBN:" for="isbn" />
<p:inputMask id="isbn" value="#{livroBean.livro.isbn}" mask="999-9-99-999999-9" validator="#{livroBean.comecaComDigitoUm}" styleClass="formLivro">
<f:ajax event="keyup" />
</p:inputMask>
<p:outputLabel value="Preço:" for="preco" />
<p:inputNumber id="preco" value="#{livroBean.livro.preco}" symbol="R$ " styleClass="formLivro">
<f:validateDoubleRange minimum="1" maximum="1000" />
<f:ajax render="msgs" event="blur"/>
<p:ajax update="preco" />
</p:inputNumber>
<p:outputLabel value="Data de Lançamento:" for="dataLancamento" />
<p:calendar id="dataLancamento" value="#{livroBean.livro.dataLancamento.time}" navigator="true" pattern="dd/MM/yyyy" mask="true" locale="pt_BR" styleClass="formLivro"/>
<p:outputLabel value="Gênero:" for="generoLivro" />
<p:selectOneMenu value="#{livroBean.livro.genero}" required="true" id="generoLivro">
<f:selectItem itemLabel="Selecione" itemValue="#{null}"/>
<f:selectItems value="#{livroBean.generos}" />
</p:selectOneMenu>
</h:panelGrid>
</p:panel>
<!-- LISTA DE AUTORES -->
<p:panel header="Autores">
<h:panelGrid columns="4">
<p:outputLabel value="Nome:" for="autor" />
<p:selectOneMenu id="autor" value="#{livroBean.autorId}">
<f:selectItem itemLabel="Selecione" noSelectionOption="true"/>
<f:selectItems value="#{livroBean.autores}" var="autor"
itemLabel="#{autor.nome}" itemValue="#{autor.id}" />
</p:selectOneMenu>
<p:commandButton value="Adicionar" action="#{livroBean.gravarAutor}" process="@this autor" update="tabelaAutores"/>
<p:commandLink value="Cadastrar novo autor" action="autor?faces-redirect=true" immediate="true" update="@all"/>
</h:panelGrid>
<p:dataTable value="#{livroBean.autoresLivro}" var="autor"
id="tabelaAutores" emptyMessage="Sem autor." type="definition">
<p:column width="50px;" headerText="Remover">
<p:commandButton action="#{livroBean.removerAutorDoLivro(autor)}" process="@this" icon="fa fa-fw fa-remove" update="tabelaAutores"/>
</p:column>
<p:column headerText="Nome do autor">
<h:outputText value="#{autor.nome}"/>
</p:column>
</p:dataTable>
</p:panel>
<p:commandButton value="Gravar" action="#{livroBean.gravar}" process="@form" update="@form :formLivros:tabelaLivros"/>
</p:fieldset>
</h:form>
<!-- LIVROS CADASTRADOS -->
<h:form id="formLivros">
<p:fieldset legend="Livros Cadastrados">
<p:dataTable value="#{livroBean.livros}" var="livro"
id="tabelaLivros" emptyMessage="Sem resultados." widgetVar="tabelaLivrosVar" filteredValue="#{livroBean.livros}" paginator="true" rows="5">
<p:column headerText="Título" sortBy="#{livro.titulo}" filterBy="#{livro.titulo}" filterMatchMode="contains">
<h:outputText value="#{livro.titulo}" />
</p:column>
<p:column headerText="ISBN">
<h:outputText value="#{livro.isbn}" />
</p:column>
<p:column headerText="Preço" sortBy="#{livro.preco}" filterBy="#{livro.preco}" filterFunction="#{livroBean.precoEhMenor}">
<h:outputText value="#{livro.preco}">
<f:convertNumber pattern="R$ #0.00" />
</h:outputText>
</p:column>
<p:column headerText="Gênero" sortBy="#{livro.genero}"
filterBy="#{livro.genero}" filterMatchMode="exact">
<f:facet name="filter">
<p:selectOneMenu onchange="PF('tabelaLivrosVar').filter()">
<f:selectItem itemLabel="Selecione" itemValue="#{null}" noSelectionOption="true"/>
<f:selectItems value="#{livroBean.generos}" />
</p:selectOneMenu>
</f:facet>
<h:outputText value="#{livro.genero}"/>
</p:column>
<p:column headerText="Data de Lançamento" sortBy="#{livro.dataLancamento.time}">
<h:outputText value="#{livro.dataLancamento.time}">
<f:convertDateTime pattern="dd/MM/yyyy" />
</h:outputText>
</p:column>
<p:column headerText="Remover">
<p:commandLink value="Remover" action="#{livroBean.removerLivro(livro)}" update="tabelaLivros" process="@this">
<p:confirm header="Confirmação" icon="ui-icon-alert" message="Deseja realmente excluir: #{livro.titulo}"/>
</p:commandLink>
</p:column>
<p:column headerText="Alterar">
<p:commandLink value="Alterar" update=":formCamposLivro">
<f:setPropertyActionListener value="#{livro}"
target="#{livroBean.livro}" />
</p:commandLink>
</p:column>
<p:column headerText="Visualizar">
<p:commandButton update=":dialogForm:livroDetail" icon="ui-icon-search" title="Ver" oncomplete="PF('livroDialog').show();">
<f:setPropertyActionListener value="#{livro}" target="#{livroBean.livro}" />
</p:commandButton>
</p:column>
<f:facet name="footer">
#{fn:length(livroBean.livros)} livros cadastrados.
</f:facet>
</p:dataTable>
</p:fieldset>
</h:form>
<h:form id="dialogForm">
<p:dialog id="livroDialog" header="Informações do Livro" widgetVar="livroDialog" modal="true" showEffect="fade" hideEffect="fade" resizable="false" width="300">
<p:outputPanel id="livroDetail" style="text-align:center" layout="block">
<p:panelGrid columns="2" rendered="#{not empty livroBean.livro}" columnClasses="value" style="width:100%;">
<f:facet name="header">
#{livroBean.livro.titulo}
</f:facet>
<h:outputText value="Código" />
<h:outputText value="#{livroBean.livro.id}" />
<h:outputText value="Preço" />
<h:outputText value="#{livroBean.livro.preco}" />
<h:outputText value="ISBN" />
<h:outputText value="#{livroBean.livro.isbn}" />
<h:outputText value="Data" />
<h:outputText value="#{livroBean.livro.dataLancamento.time}">
<f:convertDateTime pattern="dd/MM/yyyy" />
</h:outputText>
<h:outputText value="Gênero" />
<h:outputText value="#{livroBean.livro.genero}" />
<h:outputText value="Autores" />
<p:dataList value="#{livroBean.livro.autores}" var="autor" type="definition">
<h:outputText value="#{autor.nome}"/>
</p:dataList>
</p:panelGrid>
</p:outputPanel>
</p:dialog>
</h:form>
</ui:define>
<ui:define name="nomePagina">Livros</ui:define>
</ui:composition>
</html>
Métodos de gravação e exclusão:
public void gravar() {
System.out.println("Gravando livro " + this.livro.getTitulo());
if (livro.getAutores().isEmpty()) {
FacesContext.getCurrentInstance().addMessage("autor",
new FacesMessage("Livro deve ter pelo menos um Autor."));
return;
}
DAO<Livro> dao = new DAO<Livro>(Livro.class);
if (this.livro.getId() == null) {
dao.adiciona(this.livro);
this.livros = dao.listaTodos();
} else {
dao.atualiza(this.livro);
this.livros = dao.listaTodos();
}
this.livro = new Livro();
}
public void removerLivro(Livro livro) {
DAO<Livro> dao = new DAO<Livro>(Livro.class);
dao.remove(livro);
this.livros = dao.listaTodos();
}