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

Implementando ALTERAR autor

Ao clicar em ALTERAR, a tela não é preenchida com o nome do respectivo autor e apresenta a mensagem "Nome do autor é necessário!" que deve ser exibida na validação do form, ou seja, quando se clica no botão Gravar... autor.xhtml

    <h:body>
        <ui:composition template="_template.xhtml">
            <ui:define name="titulo">
                Novo autor
            </ui:define>
            <ui:define name="conteudo">
                <h:form>
                    <fieldset>
                        <legend>Dados do Autor</legend>
                        <h:panelGrid columns="2">
                            <h:outputLabel value="Nome:" for="nome" />
                            <h:inputText id="nome" value="#{autorBean.autor.nome}" required="true" requiredMessage="Nome do autor é necessário!">
                                <f:validateLength minimum="5"/>
                            </h:inputText>
                            <h:message for="nome" />
                            <h:commandButton value="Gravar" action="#{autorBean.gravar}" />
                        </h:panelGrid>
                    </fieldset>
                    <h:dataTable value="#{autorBean.autores}" var="autor" id="tabelaAutores">
                        <h:column>
                            <f:facet name="header">Nome</f:facet>
                            <h:outputText value="#{autor.nome}" />
                        </h:column>
                        <h:column>
                            <f:facet name="header">Alterar</f:facet>
                            <h:commandLink value="Altera" action="#{autorBean.carregar(autor)}"/>
                        </h:column>
                        <h:column>
                            <f:facet name="header">Remover</f:facet>
                            <h:commandLink value="Remove" action="#{autorBean.remove(autor)}"/>
                        </h:column>
                    </h:dataTable>
                </h:form>
            </ui:define>
            <ui:define name="rodape">
                Copyright SRVTech
            </ui:define>
        </ui:composition>
    </h:body>

autorBean.java:

    public void carregar(Autor autor){
        this.autor = autor;
    }
14 respostas

Fala aí Marcelo, blz?

tenta adicionar o atributo immediate=true no commandLink de alteração.

Veja se isso funciona!

Deixou de apresentar a mensagem mas ainda não está preenchendo o campo do nome do autor. Eu tinha entendido que o imediate = true servia para sair de uma página e ir para outra sem executar as validações. Mas neste caso não há saída da página. É só para popular o campo da tela...

Então o immediate=true serve para modificar um pouco a ordem do ciclo de vida do JSF.

Tente substituir a declaração do h:commandlink por esta

< h:commandLink value="Altera">
    <f:setPropertyActionListener target="#{autorBean.autor}" value="${autor}" />
</h:commandLink >

Não funcionou.

Marcelo beleza? faz o seguinte!!! deixa o metodo que tava mesmo, e lembra que você tem que por uma requisição via ajax? tenta o seu codigo na tag do html o <form coloca o atributo id. ficando assim...

E depois no seu link alterar, tem que fazer a atualizção dos campos com o ajax ficando assim...

<h:body>
        <ui:composition template="_template.xhtml">
            <ui:define name="titulo">
                Novo autor
            </ui:define>
            <ui:define name="conteudo">
                <h:form id="formularioAutor"> // coloca um id aqui.
                    <fieldset>
                        <legend>Dados do Autor</legend>
                        <h:panelGrid columns="2">
                            <h:outputLabel value="Nome:" for="nome" />
                            <h:inputText id="nome" value="#{autorBean.autor.nome}" required="true" requiredMessage="Nome do autor é necessário!">
                                <f:validateLength minimum="5"/>
                            </h:inputText>
                            <h:message for="nome" />
                            <h:commandButton value="Gravar" action="#{autorBean.gravar}" />
                        </h:panelGrid>
                    </fieldset>
                    <h:dataTable value="#{autorBean.autores}" var="autor" id="tabelaAutores">
                        <h:column>
                            <f:facet name="header">Nome</f:facet>
                            <h:outputText value="#{autor.nome}" />
                        </h:column>
                        <h:column>
                            <f:facet name="header">Alterar</f:facet>
                            <h:commandLink value="Altera" action="#{autorBean.carregar(autor)}">
                                <f:ajax render="formularioAutor"/> // Usando o ajax para atualizar a pagina
                            </h:commandLink>
                        </h:column>
                        <h:column>
                            <f:facet name="header">Remover</f:facet>
                            <h:commandLink value="Remove" action="#{autorBean.remove(autor)}"/>
                        </h:column>
                    </h:dataTable>
                </h:form>
            </ui:define>
            <ui:define name="rodape">
                Copyright SRVTech
            </ui:define>
        </ui:composition>
    </h:body>

Cara, aconselho tu a dividir sua aplicação em dois forms diferentes, um do cadastro e outra da listagem, isso pode estar envolvido o erro também, caso não resolva, poste de ManagedBean e seu DAO.

Fala Marcelo,

Para isso aqui funcionar:

<h:commandLink value="Altera">
    <f:setPropertyActionListener target="#{autorBean.autor}" value="${autor}" />
</h:commandLink >

Eu esqueci de mencionar que deve existir um setter para o atributo autor na classe AutorBean.

O que está me incomodando muito é que o form do livro está funcionando perfeitamente. Como o form do autor é mais simples, pensei que fosse apenas reproduzir o código do form do livro, fazendo as devidas alterações, e tudo funcionaria. Não quero soluções que não tenham sido mencionadas no curso. Quero apenas saber porque o campo não está sendo populado com o nome do autor quando clico no link 'alterar'. Vou postar novamente meus arquivos autor.xhtml e autorBean.java:

<?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://java.sun.com/jsf/html"
    xmlns:f="http://java.sun.com/jsf/core">

    <h:head />
    <h:body>
        <h1>Novo Autor</h1>
        <h:form id="formularioAutor" >
            <h:messages />
            <fieldset>
                <legend>Dados do Autor</legend>
                <h:panelGrid columns="2">
                    <h:outputLabel value="Nome:" for="nome" />
                    <h:inputText id="nome" value="#{autorBean.autor.nome}" required="true" requiredMessage="Cadê o nome???"/>
                    <h:commandButton value="Gravar" action="#{autorBean.gravar}" >
                        <f:ajax execute="nome" render="tabelaAutores"/>
                    </h:commandButton>
                </h:panelGrid>
                <br/>
                <h:dataTable id="tabelaAutores" value="#{autorBean.autores}" var="autor">
                    <h:column>
                        <f:facet name="header">Autores cadastrados</f:facet>
                        <h:outputText value="#{autor.nome}"/>
                    </h:column>
                    <h:column>
                        <f:facet name="header">Alterar</f:facet>
                        <h:commandLink value="Altera" action="#{autorBean.carrega(autor)}" />
                    </h:column>
                    <h:column>
                        <f:facet name="header">Remover</f:facet>
                        <h:commandLink value="Remove" action="#{autorBean.remover(autor)}" />
                    </h:column>
                </h:dataTable>
            </fieldset>
        </h:form>
    </h:body>
</html>

package br.com.caelum.livraria.bean;

import java.io.Serializable;
import java.util.List;

import javax.faces.bean.ManagedBean;
import javax.faces.bean.ViewScoped;

import br.com.caelum.livraria.dao.DAO;
import br.com.caelum.livraria.modelo.Autor;
import br.com.caelum.livraria.modelo.Livro;

@ManagedBean
@ViewScoped
public class AutorBean implements Serializable{

    private static final long serialVersionUID = 1L;

    private Autor autor = new Autor();

    public Autor getAutor() {
        return autor;
    }

    public String gravar() {

        if(this.autor.getId() == null) {
            new DAO<Autor>(Autor.class).adiciona(this.autor);            
        } else {
            new DAO<Autor>(Autor.class).atualiza(this.autor);
        }

        this.autor = new Autor();

        return "autor?faces-redirect=true";
    }

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

    public void carregar(Autor autor){
        System.out.println("carregando autor " + autor.getNome());
        this.autor = autor;
    }

    public void remover(Autor autor){
        new DAO<Autor>(Autor.class).remove(autor);
    }
}

Quando você clica ainda não está carregando?

Não.

Fala aí Marcelo blz?

Cara tenta o seguinte, crie um setter para seu atributo autor na classe AutorBean.

Altere o link de alteração para esse:

<h:commandLink value="Altera">
    <f:setPropertyActionListener target="#{autorBean.autor}" value="${autor}" />
</h:commandLink >

E veja se funciona.

Novo autor.xhtml. Ainda sem funcionar. Quando clico no link 'Alterar', ele apresenta a mensagem "Nome do autor é necessário!", que deveria apresentar somente quando clicasse no botão 'Gravar'...

<?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://java.sun.com/jsf/html"
    xmlns:f="http://java.sun.com/jsf/core"
    xmlns:ui="http://java.sun.com/jsf/facelets">

    <h:body>
        <ui:composition template="_template.xhtml">
            <ui:define name="titulo">
                Novo autor
            </ui:define>
            <ui:define name="conteudo">
                <h:form id="formAutor">
                    <fieldset>
                        <legend>Dados do Autor</legend>
                        <h:panelGrid columns="2">
                            <h:outputLabel value="Nome:" for="nome" />
                            <h:inputText id="nome" value="#{autorBean.autor.nome}" required="true" requiredMessage="Nome do autor é necessário!">
                                <f:validateLength minimum="5"/>
                            </h:inputText>
                            <h:message for="nome" />
                            <h:commandButton value="Gravar" action="#{autorBean.gravar}" >
                                <f:ajax execute="@form" render="@form :formAutor:tabelaAutores"/>
                            </h:commandButton>
                        </h:panelGrid>
                    </fieldset>
                    <h:dataTable value="#{autorBean.autores}" var="autor" id="tabelaAutores">
                        <h:column>
                            <f:facet name="header">Nome</f:facet>
                            <h:outputText value="#{autor.nome}" />
                        </h:column>
                        <h:column>
                            <f:facet name="header">Alterar</f:facet>
                            <h:commandLink value="Altera" >
                                <f:setPropertyActionListener value="#{autor}" target="#{autorBean.autor}" />
                            </h:commandLink>
                        </h:column>
                        <h:column>
                            <f:facet name="header">Remover</f:facet>
                            <h:commandLink value="Remove" action="#{autorBean.remove(autor)}"/>
                        </h:column>
                    </h:dataTable>
                </h:form>
            </ui:define>
            <ui:define name="rodape">
                Copyright SRVTech
            </ui:define>
        </ui:composition>
    </h:body>
</html>

Coloque o immediate="true"

<h:commandLink value="Altera"  immediate="true">
    <f:setPropertyActionListener value="#{autor}" target="#{autorBean.autor}" />
</h:commandLink>
solução!

Descobri o problema. Era preciso colocar a tabela com a lista dos autores em um form separado.