14 de novembro de 2010

JavaEE 5: CRUD em dialogs com PrimeFaces 1.1

A postagem de hoje pode ser considerada uma alternativa para a essa postagem: CRUD em páginas com PrimeFaces 1.1
O que difere é que invés da navegação de páginas, nós teremos nosso CRUD em uma única página, em p:dialog, e nossos avisos de sucesso ou falha se darão através do p:growl(justamente o mesmo utilizado para informar os campos obrigatórios) não haverá necessidade de em caso de falha, enviar o usuário para uma página de erro, acredito que mostrar um aviso no p:growl seja mais que suficiente e mais agradável!
Então, o projeto é o mesmo que o do link acima, só criei um novo bean(CategoriaDialogBean.java) para não alterar o atual, e uma página (dialog.jsp) para mostrar esse exemplo, lembrando que para esse exemplo não será necessário nenhuma navegação no faces-config.xml.
Imagem da operação remover:

Explicando o que vai acontecer nesse CRUD:
Inserir Categoria: A partir da imagem acima no canto superior esquerdo existe um p:commandButton chamado "Nova", ao clicar nele, o mesmo abrirá um p:dialog assim como "Alterar Categoria" que aparece no fundo do modal do p:dialog "Remover Categoria".
Alterar Categoria: O p:dialog do "Alterar Categoria" é chamado ao clicar em uma linha da p:dataTable.
Remover Categoria: O p:dialog do "Remover Categoria" é chamado pelo p:commandButton "Remover" presente no p:dialog do "Alterar Categoria"
Quanto o envio de respostas do bean, este é feito através do javax.faces.context.FacesContext e do javax.faces.application.FacesMessage. Como isso funciona? Muito simples, no próprio método eu verifico a reposta do meu DAO, que pode ser sucesso ou falha... caso seja sucesso eu mando para a view uma mensagem de sucesso, ou em caso de falha, uma mensagem de falha...

Acredito que a explicação do funcionamento dos p:dialog tenha ficado clara, então, segue os códigos-fonte do bean e do jsp, apenas lembrando que continua sendo necessário o mapeamento do bean no faces-config.xml.
CategoriaDialogBean.java:
public class CategoriaDialogBean {
    //Atributos
    private Categoria categoria = new Categoria();
    private List<Categoria> categorias;
     
    //Métodos
    public void nova(){
        categoria = new Categoria();
    }
    
    //esses são os imports necessários para o FacesContext e FacesMessage:
    //import javax.faces.application.FacesMessage;
    //import javax.faces.context.FacesContext;    
    //ao inserir uma categoria, é verificado o retorno da mesma
    //caso tenha retornado "sucesso": é retornado "Inserido com sucesso" para nossa página 
    //e chamo o metodo nova() para limpar os campos!
    //caso seha "falha": é retornado: "Falha ao inserir"
    //quem mostrará essas mensagem será o mesmo componente do primefaces que mostra a validação dos campos
    //<p:growl>, assim funciona tambem para os métodos alterar e remover!
    //detalhe importante: dessa maneira não há necessidade de estar criando a navegação de 
    //páginas no faces-config.xml, perceba que os métodos não tem retorno!
    public void inserir(){
        Categoria_DAO dao = new Categoria_DAO();
        String retorno = dao.inserir(categoria);
        FacesContext mensagem = FacesContext.getCurrentInstance();
        if(retorno.equals("sucesso")){
            mensagem.addMessage(null, new FacesMessage(FacesMessage.SEVERITY_INFO, "Inserido com sucesso", null));
            this.nova();
        } else {
            mensagem.addMessage(null, new FacesMessage(FacesMessage.SEVERITY_ERROR, "Falha ao inserir", null));
        }
    }

    public void selecionar(int codigo){
        Categoria_DAO dao = new Categoria_DAO();
        categoria = dao.selecionar(codigo);
    }

    public void alterar(){
        Categoria_DAO dao = new Categoria_DAO();
        String retorno = dao.alterar(categoria);
        FacesContext mensagem = FacesContext.getCurrentInstance();
        if(retorno.equals("sucesso")){
            mensagem.addMessage(null, new FacesMessage(FacesMessage.SEVERITY_INFO, "Alterado com sucesso", null));
        } else {
            mensagem.addMessage(null, new FacesMessage(FacesMessage.SEVERITY_ERROR, "Falha ao alterar", null));
        }
    }

    public void remover(){
        Categoria_DAO dao = new Categoria_DAO();
        String retorno = dao.remover(categoria.getCodigo());
        FacesContext mensagem = FacesContext.getCurrentInstance();
        if(retorno.equals("sucesso")){
            mensagem.addMessage(null, new FacesMessage(FacesMessage.SEVERITY_INFO, "Removido com sucesso", null));
            this.nova();
        } else {
            mensagem.addMessage(null, new FacesMessage(FacesMessage.SEVERITY_ERROR, "Falha ao remover", null));
        }
    }

    //Getters e Setters

    public Categoria getCategoria() {
        return categoria;
    }

    public void setCategoria(Categoria categoria) {
        this.categoria = categoria;
    }

    public List<Categoria> getCategorias() {
        Categoria_DAO dao = new Categoria_DAO();
        categorias = dao.listar();
        return categorias;
    }

    public void setCategorias(List<Categoria> categorias) {
        this.categorias = categorias;
    }

}


Mapeamento do bean no faces-config.xml:
<managed-bean>
  <managed-bean-name>categoriaDialogBean</managed-bean-name>
  <managed-bean-class>control.CategoriaDialogBean</managed-bean-class>
  <managed-bean-scope>session</managed-bean-scope>
</managed-bean>


dialog.jsp:
<%@ taglib uri="http://java.sun.com/jsf/html" prefix="h"%>
<%@ taglib uri="http://java.sun.com/jsf/core" prefix="f"%>
<%@ taglib uri="http://primefaces.prime.com.tr/ui" prefix="p"%>

<html>
<f:view>
    <head>
    <title>Categorias</title>
    <p:resources />
    </head>
    <body>
        <p:growl id="aviso" />
    
    <h:form id="formCategorias">
        <p:commandButton value="Nova" actionListener="#{categoriaDialogBean.nova}" oncomplete="inserir.show()" update="formInserir" />

        <p:dataTable value="#{categoriaDialogBean.categorias}" var="c"
            paginator="true" rows="5" emptyMessage="Categorias não encontradas!" selectionMode="single" 
            selection="#{categoriaDialogBean.categoria}" update="formAlterar" onselectComplete="alterar.show()">
            <p:column>
                <f:facet name="header">
                    <h:outputText value="Codigo" />
                </f:facet>
                <h:outputText value="#{c.codigo}" />
            </p:column>
            <p:column filterBy="#{c.nome}">
                <f:facet name="header">
                    <h:outputText value="Nome" />
                </f:facet>
                <h:outputText value="#{c.nome}" />
            </p:column>
            <p:column>
                <f:facet name="header">
                    <h:outputText value="Valor" />
                </f:facet>
                <h:outputText value="#{c.valor}" />
            </p:column>
            <p:column>
                <f:facet name="header">
                    <h:outputText value="Data" />
                </f:facet>
                <h:outputText value="#{c.data}">
                    <f:convertDateTime pattern="dd/MM/yyyy" />
                </h:outputText>
            </p:column>
        </p:dataTable>
    </h:form>
    
    <p:dialog widgetVar="inserir" header="Inserir Categoria" width="320" modal="true">
        <h:form id="formInserir">
            <h:panelGrid columns="2">
                <h:outputText value="Nome" />
                <h:inputText value="#{categoriaDialogBean.categoria.nome}" required="true" requiredMessage="Informe o nome" />
                <h:outputText value="Valor" />
                <h:inputText value="#{categoriaDialogBean.categoria.valor}" required="true" requiredMessage="Informe o valor" />
                <h:outputText value="Data" />
                <p:calendar value="#{categoriaDialogBean.categoria.data}" pattern="dd/MM/yyyy" locale="pt_BR" required="true" requiredMessage="Informe a data" />
                <p:commandButton value="Salvar" action="#{categoriaDialogBean.inserir}" update="aviso,formInserir,formCategorias" />
                <p:commandButton value="Cancelar" immediate="true" onclick="inserir.hide()" />
            </h:panelGrid>
        </h:form>    
    </p:dialog>
    
    <p:dialog widgetVar="alterar" header="Alterar Categoria" width="350">
        <h:form id="formAlterar">
            <h:panelGrid columns="2">
                <h:outputText value="Nome" />
                <h:inputText value="#{categoriaDialogBean.categoria.nome}" required="true" requiredMessage="Informe o nome" />
                <h:outputText value="Valor" />
                <h:inputText value="#{categoriaDialogBean.categoria.valor}" required="true" requiredMessage="Informe o valor" />
                <h:outputText value="Data" />
                <p:calendar value="#{categoriaDialogBean.categoria.data}" pattern="dd/MM/yyyy" locale="pt_BR" required="true" requiredMessage="Informe a data" />
            </h:panelGrid>
            <p:commandButton value="Salvar" action="#{categoriaDialogBean.alterar}" update="aviso,formAlterar,formCategorias" />
            <p:commandButton value="Remover" update="formRemover" oncomplete="remover.show()"/>
            <p:commandButton value="Cancelar" immediate="true" onclick="alterar.hide()" />
        </h:form>    
    </p:dialog>
    
    <p:dialog widgetVar="remover" header="Remover Categoria" width="400" modal="true">
        <h:form id="formRemover">
            <h:outputText value="Confirma a remoção: #{categoriaDialogBean.categoria.nome} ?" />
            <h:panelGrid columns="2">
                <p:commandButton value="Sim" action="#{categoriaDialogBean.remover}" update="aviso,formCategorias" oncomplete="alterar.hide(), remover.hide()" />
                <p:commandButton value="Não" onclick="remover.hide()" />
            </h:panelGrid>
        </h:form>    
    </p:dialog>
    
    </body>
</f:view>
</html>
Ah... peço desculpas pela demora da postagem, é que ando com problemas com minha internet! rsrs

Mas está aí!



=)

8 comentários:

  1. Hun excelente! Muito obrigado por compartilhar ;)
    beijos...

    ResponderExcluir
  2. Olá amigo
    Quando faço a ação alterar, como que ele captura o código?
    Pois não estou conseguindo fazer a ação de alterar. ele faz um insert, pois o código chega no bean como 0

    ResponderExcluir
  3. Primeiramente é amigA! hahaha
    Esse exemplo ele não passa o código, a própria p:datatable tem a propriedade selectionMode="single" que diz que é pra selecionar apenas um objeto, e a propriedade
    selection="#{categoriaDialogBean.categoria}"
    que ao clicar na linha da tabela, já seta no bean qual é a categoria selecionada! Dê uma olhadinha no escopo do seu bean, se tiver como request, pode ser esse o problema..;)

    ResponderExcluir
  4. Desculpe pelo AmigO, é difícil ver mulheres blogando sobre tecnologia.


    Sim está como request. Grato!

    ResponderExcluir
  5. Olá Andii,

    Neste teu código, como devo fazer para após selecionar uma linha da tabela, ocorra o direcionamento para outra pm:view ou página jsf, levando os dados da linha selecionada ?

    Grato,
    Vicente :)

    ResponderExcluir
    Respostas
    1. Olá Vicente! Eu geralmente faço isso usando o escopo @SessionScoped... sei que essa não é a melhor opção...Veja se o ui:param dessa postagem pode te ajudar: http://javasemcafe.blogspot.com/2011/03/jsf-20-utilizacao-de-facelets.html

      Excluir
  6. Olá senhorita, mas meu componente datable não possui este evento/atributo :onselectComplete="alterar.show()"

    Estou usando primefaces 3.0 , será que deixei passar algum detalhe ??

    Muito Obrigado !!!!

    ResponderExcluir
    Respostas
    1. Olá Alex!
      O problema é que muitaa coisa mudou no primefaces da versão 1.1 (usado nesta postagem) até a versão 3.0.
      Na versão 3.0, a forma que eu encontrei de alterar os dados é colocando um commandButton em uma coluna, mas dá uma olhada neste exemplo: http://www.primefaces.org/showcase/ui/datatableRowSelectionInstant.jsf espero que te ajude.

      Excluir

Deixe seu comentário... ;)