Solucionado (ver solução)
Solucionado
(ver solução)
11
respostas

CommandLink dentro da DataTable não faz update na tabela!

Meu commandLink parou de funcionar:

<p:column headerText="Remover">
    <h:commandLink value="Remover" action="#{livroBean.remover(livro)}" />
</p:column>

Ele remove o livro do banco, verifiquei o PhaseListener e ele já chega na RENDER_RESPONSE, mas não atualiza a tabela com os livros, ele continua lá! Tenho que atualizar a página para fazê-lo sumir.

Atualizei então o mesmo para um CommandButton, da seguinte forma:

<p:column headerText="Remover">
                    <p:commandButton icon="fa fa-fw fa-remove"
                        actionListener="#{livroBean.remover(livro)}" process="@form"
                        update="@form" />
                </p:column>

Mas também não funciona. Já tentei utilizar o process="@form" e update="@form", mas nada adianta.

11 respostas

posta seu html inteiro para gente ver

<?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:p="http://primefaces.org/ui"
    xmlns:ui="http://xmlns.jcp.org/jsf/facelets">

<ui:composition template="_template.xhtml">

    <f:metadata>
        <f:viewParam name="livroId" value="#{livroBean.livro.id}" />
        <f:viewAction action="#{livroBean.carregarLivroPelaId}"
            if="#{param.livroId != null}" />
    </f:metadata>


    <ui:define name="titulo">
        <p:outputPanel>Novo Livro</p:outputPanel>
    </ui:define>

    <ui:define name="conteudo">
        <h:form id="livro">

            <p:messages id="messages" />

            <p:fieldset legend="Dados do Livro">
                <p: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="Título não pode ser superior a 40">
                        <f:validateLength maximum="40" />
                        <f:ajax event="blur" render="messages" />
                    </p:inputText>

                    <p:outputLabel value="ISBN:" for="isbn" />
                    <p:inputMask id="isbn" value="#{livroBean.livro.isbn}"
                        validator="#{livroBean.comecaComDigitoUm}"
                        mask="999-9-99-999999-9" />

                    <p:outputLabel value="Preço:" for="preco" />
                    <p:inputText id="preco" value="#{livroBean.livro.preco}" />

                    <p:outputLabel value="Data de Lançamento:" for="dataLancamento" />
                    <p:calendar id="dataLancamento"
                        value="#{livroBean.livro.dataLancamento.time}"
                        pattern="dd/MM/yyyy" timeZone="America/Sao_Paulo" mask="true" />

                </p:panelGrid>

            </p:fieldset>

            <br />

            <p:fieldset legend="Dados do Autor">

                <p:panelGrid columns="4">
                    <p:outputLabel value="Selecione Autor:" for="autor" />
                    <p:selectOneMenu value="#{livroBean.autorId}" id="autor">
                        <f:selectItems value="#{livroBean.autores}" var="autor"
                            itemLabel="#{autor.nome}" itemValue="#{autor.id}" />
                    </p:selectOneMenu>
                    <p:commandButton value="Gravar Autor"
                        action="#{livroBean.gravarAutor}" process="@this autor"
                        update="tabelaAutores" />

                    <p:commandLink value="ou cadastrar novo autor"
                        action="#{livroBean.formAutor}" immediate="true" update="@all" />
                </p:panelGrid>

                <p:dataTable value="#{livroBean.autoresDoLivro}" var="autor"
                    id="tabelaAutores" emptyMessage="Nenhum autor">
                    <p:column>
                        <h:outputText value="#{autor.nome}" />
                    </p:column>
                    <p:column>
                        <p:commandLink value="X"
                            action="#{livroBean.removerAutorDoLivro(autor)}"
                            update="tabelaAutores" process="@this" />
                    </p:column>
                </p:dataTable>
            </p:fieldset>

            <br />

            <h:panelGrid style="margin: 0 auto">
                <p:commandButton value="Gravar" action="#{livroBean.gravar}"
                    process="@form" update="@form :formTabelaLivros:tabelaLivros" />
            </h:panelGrid>
        </h:form>

        <br />

        <h:form id="formTabelaLivros">
            <p:dataTable value="#{livroBean.livros}" var="livro"
                id="tabelaLivros" paginator="true" rows="5">

                <f:facet name="header">Livros</f:facet>
                <p:column headerText="Título" sortBy="#{livro.titulo}"
                    filterBy="#{livro.titulo}" filterMatchMode="startsWith">
                    <h:outputText value="#{livro.titulo}" />
                </p:column>

                <p:column headerText="ISBN" sortBy="#{livro.isbn}">
                    <h:outputText value="#{livro.isbn}" />
                </p:column>

                <p:column headerText="Preço" sortBy="#{livro.preco}">
                    <h:outputText value="#{livro.preco}">
                        <f:convertNumber type="currency" pattern="R$ #0.00"
                            currencySymbol="R$" locale="pt_BR" />
                    </h:outputText>
                </p:column>

                <p:column headerText="Data" sortBy="#{livro.dataLancamento.time}">
                    <h:outputText value="#{livro.dataLancamento.time}">
                        <f:convertDateTime pattern="dd/MM/yyyy"
                            timeZone="America/Sao_Paulo" />
                    </h:outputText>
                </p:column>

                <p:column headerText="Alterar">
                    <p:commandButton icon="fa fa-fw fa-edit"
                        actionListener="#{livroBean.carregar(livro)}" update=":livro" />
                </p:column>

                <p:column headerText="Remover">
                    <p:commandButton icon="fa fa-fw fa-remove"
                        actionListener="#{livroBean.remover(livro)}" process="@form"
                        update="@form" />
                </p:column>

            </p:dataTable>
        </h:form>
    </ui:define>
</ui:composition>

</html>

Não vi nada de errado ai no olho por olho, só tenta modificar ficando assim.

        <h:form id="formTabelaLivros">
            <p:dataTable value="#{livroBean.livros}" var="livro"
                id="tabelaLivros" paginator="true" rows="5">

                <f:facet name="header">Livros</f:facet>
                <p:column headerText="Título" sortBy="#{livro.titulo}"
                    filterBy="#{livro.titulo}" filterMatchMode="startsWith">
                    <h:outputText value="#{livro.titulo}" />
                </p:column>

                <p:column headerText="ISBN" sortBy="#{livro.isbn}">
                    <h:outputText value="#{livro.isbn}" />
                </p:column>

                <p:column headerText="Preço" sortBy="#{livro.preco}">
                    <h:outputText value="#{livro.preco}">
                        <f:convertNumber type="currency" pattern="R$ #0.00"
                            currencySymbol="R$" locale="pt_BR" />
                    </h:outputText>
                </p:column>

                <p:column headerText="Data" sortBy="#{livro.dataLancamento.time}">
                    <h:outputText value="#{livro.dataLancamento.time}">
                        <f:convertDateTime pattern="dd/MM/yyyy"
                            timeZone="America/Sao_Paulo" />
                    </h:outputText>
                </p:column>

                <p:column headerText="Alterar">
                    <p:commandButton icon="fa fa-fw fa-edit"
                        actionListener="#{livroBean.carregar(livro)}" update=":livro" />
                </p:column>

                <p:column headerText="Remover">
                    <p:commandButton icon="fa fa-fw fa-remove"
                        actionListener="#{livroBean.remover(livro)}" 
                        update="formTabelaLivros" />
                </p:column>

            </p:dataTable>
        </h:form>

Mesma coisa... tá bem complicado resolver isso. Meu método Remover está da seguinte forma:

    public void remover(Livro livro) {
        System.out.println("Removendo livro");
        new DAO<Livro>(Livro.class).remove(livro);
    }

O mais estranho é que para remover um Autor, o método utilizado é idêntico, e tudo funciona instantaneamente. A única diferença é que a visualização de autores está em um p:dataList e não em um p:dataTable.

Fellipe tenta fazer o update atualizar direto no seu metodo remover, me passa todo o seu bean para dar uma olhada?

Fiz um teste da seguinte forma para verificar se seria uma inconsistência da p:dataTable:

            <p:dataList value="#{livroBean.livros}" var="livro" type="definition">
                <f:facet name="header">
                        Livros
                    </f:facet>

                <p:commandButton icon="fa fa-fw fa-remove"
                    action="#{livroBean.remover(livro)}" update="@form" />

                    #{livro.titulo}
            </p:dataList>

O mesmo problema ocorre. Não consigo entender como a página Autor.xhtml não sofre desse problema.

Método LivroBean:

@ManagedBean
@ViewScoped
public class LivroBean implements Serializable {

    private static final long serialVersionUID = 1L;

    private Livro livro = new Livro();

    private Integer autorId;

    private List<Livro> livros;

    public void setAutorId(Integer autorId) {
        this.autorId = autorId;
    }

    public Integer getAutorId() {
        return autorId;
    }

    public Livro getLivro() {
        return livro;
    }

    public List<Livro> getLivros() {

        DAO<Livro> dao = new DAO<Livro>(Livro.class);

        if(this.livros == null) {
            this.livros = dao.listaTodos();            
        }

        return livros;
    }

    public List<Autor> getAutores() {
        return new DAO<Autor>(Autor.class).listaTodos();
    }

    public List<Autor> getAutoresDoLivro() {
        return this.livro.getAutores();
    }

    public void carregarLivroPelaId() {
        this.livro = new DAO<Livro>(Livro.class).buscaPorId(this.livro.getId()); 
    }

    public void gravarAutor() {
        Autor autor = new DAO<Autor>(Autor.class).buscaPorId(this.autorId);
        this.livro.adicionaAutor(autor);
        System.out.println("Escrito por: " + autor.getNome());
    }

    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.livro = new Livro();
    }

    public void remover(Livro livro) {
        System.out.println("Removendo livro");
        new DAO<Livro>(Livro.class).remove(livro);
    }

    public void removerAutorDoLivro(Autor autor) {
        this.livro.removeAutor(autor);
    }

    public void carregar(Livro livro) {
        System.out.println("Carregando livro");
        this.livro = livro;
    }

    public String formAutor() {
        System.out.println("Chamanda do formulário do Autor.");
        return "autor?faces-redirect=true";
    }

    public void comecaComDigitoUm(FacesContext fc, UIComponent component,
            Object value) throws ValidatorException {

        String valor = value.toString();
        if (!valor.startsWith("1")) {
            throw new ValidatorException(new FacesMessage(
                    "ISBN deveria começar com 1"));
        }

    }
}

Como faço para atualizar no método remover? Dessa forma?

public void remover(Livro livro) {
        System.out.println("Removendo livro");
        new DAO<Livro>(Livro.class).remove(livro);

        this.getLivros();        
    }

Tanto com this.getLivros(); quanto this.livros = this.getLivros(); resultam no mesmo problema.

solução!

Tenta assim.

public void remover(Livro livro) {
        System.out.println("Removendo livro");
        new DAO<Livro>(Livro.class).remove(livro);
     DAO<Livro> dao = new DAO<Livro>(Livro.class);
    this.livros = dao.listaTodos();
    }

Deu certo! Finalmente! Hehehe

Só não entendo como o mesmo não é necessário para a página Autor.xhtml...

De qualquer forma, muitíssimo obrigado! Grande abraço!

Fellipe que bom que deu certo parceiro. Deve ser por causa do sortby ou filterby da sua tabela sempre quando usam isso ele faz isso mesmo! Ta na documentação la no primefaces, mais de qualquer forma é só usar assim hehe. Valeu um otímo estudo e um grande abraço!

Quer mergulhar em tecnologia e aprendizagem?

Receba a newsletter que o nosso CEO escreve pessoalmente, com insights do mercado de trabalho, ciência e desenvolvimento de software