Solucionado (ver solução)

Importante

Você está vendo a versão anterior da nova experiência da Alura que estamos preparando para você. Em breve, ela ganha uma identidade visual novinha totalmente pensada em potencializar seus estudos!

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.