Problemas com campos CPF e CNPJ.

27/04/2010

Saudações equipe de mestres do suporte técnico Devmedia. Sou acadêmico e estou desenvolvendo um pequeno sistema de conclusão de semestre de cadastro de anuncios classificados de produtos e serviços, estou seguindo as video aulas do Dyego Carmo, mais especificamente "DESENVOLVENDO UM SISEMA COMPLETO COM JPA" e os demais tutoriais do canal java para aprender JSF e adpatar no meu sistema, beleza, já consegui muita coisa, mas como sempre, algumas coisas são mais difíceis de adaptar. vamos lá. Na minha entidade Usuario, tenho os campos. @Column(name = "pessoa_fisica") private Boolean pessoa_fisica; @Column(name = "pessoa_juridica") private Boolean pessoa_juridica; @Column(name = "cpf_cnpj") private String cpf_cnpj; O meu UsuarioDAO tá funcionando beleza, criei os teste Junit, como nas video aulas e tá funcionando, o JPAUtil tambem tá funcionando. Meu bean gerenciado tá assim. import br.com.webtrade.dao.UsuarioDAO; import br.com.webtrade.entity.Usuario; import java.util.List; /** * * @author Administrador */ public class UsuariosFace { private final UsuarioDAO dao = new UsuarioDAO(); private List usuarios; private Usuario usuarioInEdit; public UsuariosFace() { } public String doStartAdd(){ usuarioInEdit = new Usuario(); return "goAdUsuario"; } public String finishAdd(){ dao.addUsuario(usuarioInEdit); usuarios = null; return "goListaUsuario"; } public List getUsuarios() { if(usuarios == null){ usuarios=dao.getAllUsuario(); } return usuarios; } public void setUsuarios(List usuarios) { this.usuarios = usuarios; } public Usuario getUsuarioInEdit() { return usuarioInEdit; } public void setUsuarioInEdit(Usuario usuarioInEdit) { this.usuarioInEdit = usuarioInEdit; } } E na pagina jsf tenho os campos: A questão é. tá tudo cadastrando beleza, porém nao consigo cadastrar a opção do selectOneRadio cpf ou cnpj, dependendo da escolha do usuário. E caso o usuario escolha cpf, o metodo #{UsuariosFace.usuarioInEdit.cpf_cnpj} faça a validação do cpf, e caso seja a escolha cnpj, o mesmo faça a validação do cnpj. Caros mestres, por hora é só isso que preciso para continuar avançando no meu projeto de estudos e passar pra proxima fase, que é o cadatro de produtos. agradeço pelo suporte e espero por uma resposta. muito obrigado a todos, caso precisem de mais informações, estou pronto a fornecer. Rodrigo Ozanan Vieira. dhigoos@bol.com.br
Rodrigo Vieira

Rodrigo Vieira

Curtidas 0

Respostas

Henrique Weissmann

Henrique Weissmann

27/04/2010

Oi Rodrigo,

minha sugestão neste caso é a seguinte: o selectRadio é usado para selecionar qual o tipo de cadastro que você vai preencher, e não o campo textual que preencherá o seu bean.

Sendo assim, relacione o seu selectOneRadio com uma propriedade do seu backing bean e crie um novo campo textual para preencher um valor genérico, seja ele CNPJ ou CPF. Este campo textual deverá estar relacionado com uma propriedade textual do managed bean correspondente, e não da entidade que for persistida.

Assim, no momento de submissão, você verificará se trata-se de CNPJ ou CPF no managed bean, fará a validação apropriada e, em caso de invalidação, retornará uma mensagem de erro para o usuário.
GOSTEI 0
Rodrigo Vieira

Rodrigo Vieira

27/04/2010


Caro Lobo, e como é que faz então, me ajuda a implementar isso, pois nao estou conseguindo,
como relacionar o backing bean e o selectoneradio pra o usuario escolher entre cpf e cnpj ? e a validação dos mesmos ?

Como voce pediu pelo e-mail vou repostar o conteudo original da minha duvida.


Na minha entidade Usuario, tenho os campos.

@Column(name = "pessoa_fisica")
private Boolean pessoa_fisica;

@Column(name = "pessoa_juridica")
private Boolean pessoa_juridica;

@Column(name = "cpf_cnpj")
private String cpf_cnpj;

O meu UsuarioDAO tá funcionando beleza, criei os teste Junit, como nas video aulas e tá funcionando, o JPAUtil tambem tá funcionando.


Meu backing bean tá assim.


package br.com.webtrade.faces.bean;

import br.com.webtrade.dao.UsuarioDAO;
import br.com.webtrade.entity.Usuario;
import java.util.List;


public class UsuariosFace {

    private final UsuarioDAO dao = new UsuarioDAO();
    private List<Usuario> usuarios;
    private Usuario usuarioInEdit;
  

    public UsuariosFace() {
    }

    public String doStartAdd(){
        usuarioInEdit = new Usuario();
        return "goAdUsuario";
    }

    public String finishAdd(){
        dao.addUsuario(usuarioInEdit);
        usuarios = null;
        return "goListaUsuario";      
    }

    public List<Usuario> getUsuarios() {
        if(usuarios == null){
            usuarios=dao.getAllUsuario();
        }
        return usuarios;
    }

    public void setUsuarios(List<Usuario> usuarios) {
        this.usuarios = usuarios;
    }

    public Usuario getUsuarioInEdit() {
        return usuarioInEdit;
    }

    public void setUsuarioInEdit(Usuario usuarioInEdit) {
        this.usuarioInEdit = usuarioInEdit;
    }    
}


E na pagina jsf tenho os campos: 

<h:selectOneRadio id="fis_jur" style="position: absolute; left: 400px; top: 190px" layout="pageDirection">
<f:selectItem id="cpf" itemLabel="P. Fisica" itemValue="#{UsuariosFace.usuarioInEdit.pessoa_fisica}"/>
<f:selectItem id="cnpj" itemLabel="P. Juridica" itemValue="#{UsuariosFace.usuarioInEdit.pessoa_Juridica}"/>
<h:selectOneRadio/>      


<h:outputText value="CPF/CNPJ :" style="font-weight: bold; font-family: verdana;
font-size: 14px; position: absolute; left: 300px; top: 280px" />
<h:inputText id="cpfnpj" size="20" style="position: absolute; left: 400px; top: 280px"
value="#{UsuariosFace.usuarioInEdit.cpf_cnpj}"/>


A questão é. tá tudo cadastrando beleza, porém nao consigo cadastrar a opção do selectOneRadio cpf ou cnpj, dependendo da escolha do usuário. E caso o usuario escolha cpf, preciso que o metodo #{UsuariosFace.usuarioInEdit.cpf_cnpj} faça a validação e o cadastro do cpf, e caso seja a escolha cnpj, o mesmo faça a validação e cadastro do cnpj.

Caros mestres, por hora é só isso que preciso para continuar avançando no meu projeto de estudos e passar pra proxima fase, que é o cadatro de produtos.

Agradeço pelo suporte e espero por uma resposta. muito obrigado a todos, caso precisem de mais informações, estou pronto a fornecer.

Rodrigo Ozanan Vieira.
dhigoos@bol.com.br

GOSTEI 0
Henrique Weissmann

Henrique Weissmann

27/04/2010

Oi Rodrigo, vamos por partes então.

A começar pela sua página JSF:

Ela terá o trecho que você mencionou acima mais ou menos como este:

<h:selectOneRadio id="fis_jur" style="position: absolute; left: 400px; top: 190px" layout="pageDirection" value="#{seuBean.tipoEntrada}">
<f:selectItem id="cpf" itemLabel="P. Fisica" itemValue="#{UsuariosFace.usuarioInEdit.pessoa_fisica}"/>
<f:selectItem id="cnpj" itemLabel="P. Juridica" itemValue="#{UsuariosFace.usuarioInEdit.pessoa_Juridica}"/>
<h:selectOneRadio/>      


<h:outputText value="CPF/CNPJ :" style="font-weight: bold; font-family: verdana;
font-size: 14px; position: absolute; left: 300px; top: 280px" />
<h:inputText id="cpfnpj" size="20" style="position: absolute; left: 400px; top: 280px"
value="#{seuBean.cpf_cnpj}"/>

Repare que relacionei o valor do selectOneRadio com uma propriedade do seu managed bean relacionado.

Agora, vamos para o seu managed bean: supondo que a action executeCNPJCPF do seu bean é que fosse ser executada pelo formulário.

Ela seria em pseudo-código mais ou menos como o código abaixo:

public String executeCNPJCPF() {
   String tipoEntrada = getTipoEntrada();
   if (! valideCNPJCPF(getCpf_cnpj(), tipoEntrada)) {
           // Enviamos uma mensagem para o nosso usuário
           FacesContext contextoFaces = FacesContext.getCurrentInstance();
           contextoFaces.addMessage(idCliente, new FacesMessage("Opa! CPF ou CNPJ inválido!"));
           return null;// retornamos para a mesma view que fez o chamado
   }
   /*
          O managed bean faz então o que tem de fazer e retorna para a action relacionada
   */
   return "action";
}


GOSTEI 0
Rodrigo Vieira

Rodrigo Vieira

27/04/2010


 Caro Lobo, estou quase resolvendo o problema, eu gostaria de saber é o seguinte.

como faço para mudar dinamicamente compontentes em tempo de execução, exemplo.

criei um selectOneMenu com as opções "Pessoa Fisica" e "Pessoa Juridica", por padrão está em "Pessoa Fisica", e abaixo tem um inputText ja com mascara e validando o cpf, e outro inputText validando cnpj com rendered="false" e required="false", a duvida, como eu faço para, quando eu escolher  "Pessoa Juridica" no meu selectOneMenu, automaticamente esconder meu campo cpf e torna-lo nao requerido para que o metodo get possa ser acionado, e mostrar meu campo cnpj e torna-lo required="true" e vice-versa, creio que voce entendeu, ou seja, ao escolher um, o outro é desabiliado.

isso é feito na propria pagina jsf ou através de binding do componente no bean gerenciado?
acho que agora tá bem mais facil.
estou aguardo, valeu.
GOSTEI 0
Henrique Weissmann

Henrique Weissmann

27/04/2010

Oi Rodrigo,

neste caso você terá de usar Javascript. Como você mencionou, o objetivo é que conforme o usuário selecione uma das opções em uma caixa radio button determinado componente (como por exemplo um campo textual) torne-se visível ou não.

O primeiro passo é atribuir um id a cada componente da sua página (incluindo o radio button). Em seguida, inclua no radiobutton a tag onchange="nome da função javascript". Vou fazer um exemplo bem simples aqui mas que ilustra bem o que deve ser feito:

Suponha que haja uma tag como a abaixo na sua página:

<h:selectOneRadio id="radio">
  <opções aqui dentro>
</h:selectOneRadio>

E que haja dois elementos textuais: um input do tipo text chamado cnpj e outro chamado cpf como no exemplo abaixo:

<input type="text" id="cnpj"/>
<input type="text" id="cpf"/>

Em um momento inicial não é interessante que os dois estejam visíveis. Sendo assim no segundo passo, você tem duas alternativas.

a) Pode via CSS definir qual componente que por default é invisível, tal como no exemplo abaixo:
#cnpj {
   display: none;
}
Como se trata de algo específico de uma página, é melhor você incluir esta propriedade css em um arquivo separado específico OU dentro da tag <style> da própria página.

b) Pode incluir um código Javascript que, no final do carregamento da página, já faça a escolha entre qual componente deverá estar visível ou não. O que nos leva ao terceiro passo.

Terceiro passo: a escrita do código Javascript. Vamos supor que o nome da função Javascript que verifique qual componente expor seja chamada mudarComponentes(). Seu código poderia ser como o abaixo:

<script type="text/javascript">
   function mudarComponentes() {
      var valorRadio = document.getElementById("radio").value // obtenho o valor do radio
      if (valorRadio == "cpf") {
          var elemento = document.getElementById("cpf")
          // oculta cnpj
          document.getElementById("cpf").style("display") = 'block'
          document.getElementById("cnpj").style("display") = 'none'
      } else {
          var elemento = document.getElementById("cnpj")
          // o contrário
           document.getElementById("cpf").style("display") = 'block'
          document.getElementById("cnpj").style("display") = 'none'

      }
     
  }
</script>

É uma função bem básica, e que com certeza pode ser melhor escrita. Mas já serve para dar uma idéia geral. Voltando ao que é exposto inicialmente, você poderia no final da sua página incluir o código abaixo:
<script type="text/javascript">
     mudarComponentes()
</script>

Coloque-a no final da página (dentro da tag body) porque assim garantirá que seja executada somente após o restante da página ter sido carregado ok?

No entanto, nem tudo são flores com JSF. É muito comum em algumas distribuições o id, apesar de definido pelo programador, ser alterado em tempo de execução. Neste caso, faça o seguinte: abra a página renderizada pelo seu navegador e verifique o id gerado. Se alterado, use o valor alterado.

Há também um atributo que pode ser incluido chamado forceId="true". Porém em algumas implementações não funciona muito bem.

Outra dica muito bacana é você aprender jQuery (http://www.jquery.com), que pode ser visto em algumas horas e é muito mais produtivo que o JavaScript convencional.
GOSTEI 0
Rodrigo Vieira

Rodrigo Vieira

27/04/2010


Poxa camarada, tá dificil, já tentei de toda forma implementar essa funçao mas nao consigo, consegui ocultar o campo cnpj via css como voce falou, mas a função nao estou conseguindo implementar, tem como voce ser mais claro e objetivo, estou entendendo o que quer dizer, mas está meio vago, vou te mostrar os componentes que quero interagir.



Na pagina JSF estes componentes estão declarados assim, chamando a função no onchange.


<h:selectOneMenu id="fis_jur"  onchange="mudarPessoa" value="#{UsuariosFace.usuarioInEdit.fis_jur}">

                <f:selectItem itemValue="Fisica" itemLabel="Fisica" />
                <f:selectItem itemValue="Juridica" itemLabel="Juridica"/>

</h:selectOneMenu>

<easy:inputCpf  requiredMessage="CPF Invalido"  id="inputCpf" value="#{UsuariosFace.usuarioInEdit.cpf}" required="true" submitWithMask="true" useMask="true" useValidate="true" useMaskSize="true" placeHolder="_" styleClass="cpfvalido">
          
            <h:outputLabel  for="inputCpf" value="Cpf:" styleClass="labelcpf"
            style="font-weight: bold; font-family: verdana; font-size: 14px;
            position: absolute; left: 300px; top: 250px"/>

</easy:inputCpf>

<easy:inputCnpj requiredMessage="CNPJ Invalido"  id="inputCnpj" value="{UsuariosFace.usuarioInEdit.cnpj}"
required="true" submitWithMask="true" useMask="true" useValidate="true" useMaskSize="true" placeHolder="_" styleClass="cnpjvalido">

           <h:outputLabel  for="inputCnpj" value="Cnpj:" styleClass="labelcnpj"
           style="font-weight: bold; font-family: verdana; font-size: 14px;
           position: absolute; left: 300px; top: 280px"/>

</easy:inputCnpj>


e a função que voce me passou eu tentei implementar assim

<script type="text/javascript">
   function mudarPessoa() {
      var valorMenu = document.getElementById("fis_jur").value; // obtenho o valor do radio
      if (valorMenu == "Fisica") {
          var elemento = document.getElementById("Fisica");
          // oculta cnpj
          document.getElementById("inputCpf").style("display") = 'block';
          document.getElementById("inputCnpj").style("display") = 'none';
      } else {
          var elemento = document.getElementById("Juridica");
          // o contrário
          document.getElementById("inputCpf").style("display") = 'none';
          document.getElementById("inputCnpj").style("display") = 'block';
      }
  }
</script>

Nao funciona de jeito nenhum, o que acho estranho é a variavel elemento nao é usada em momento
nenhuma.
te peço que seja um pouco mais objetivo na proxima resposta.

agradeço pela atenção.

Rodrigo.


GOSTEI 0
Henrique Weissmann

Henrique Weissmann

27/04/2010

Oi Rodrigo,

Algumas coisas precisam ser validadas então:
1. Você verificou no código fonte retornado ao seu navegador como estão sendo gerados os identificadores das suas tags? Como mencionei no post anterior, de vez em algumas implementações do JSF este é manipulado pelo framework, sobrescrevendo assim o inicialmente estipulado pelo desenvolvedor.

2. O seu código JavaScript está sendo executado após a página ter sido carregada? Isto é fácil de verificar: simplesmente inclua instruções alert("Algum texto") no interior da sua função. Caso ela esteja sendo executada, aparecerão caixas de diálogo para você.

3. Verifique o evento onchange da sua tag. Você deve digitar mudarPessoa(), e não apenas mudarPessoa. Isto porque você está chamando uma função em Javascript. Tal como você colocou, o código JavaScript vai ser interpretado como inválido.

Agora, de volta ao seu problema: bem observado, a variável elemento realmente não serve para nada. E encontrei um erro no código que te enviei inclusive. Me desculpe por isto.

Aqui segue uma versão atualizada do mesmo:

<script type="text/javascript">
   function mudarPessoa() {
      var valorMenu = document.getElementById("fis_jur").value; // obtenho o valor do radio
      if (valorMenu == "Fisica") {
          // oculta cnpj
          document.getElementById("inputCpf").style.display = 'block';
          document.getElementById("inputCnpj").style.display = 'none';
      } else {
          // o contrário
          document.getElementById("inputCpf").style.display = 'none';
          document.getElementById("inputCnpj").style.display = 'block';
      }
  }
</script>

GOSTEI 0
Rodrigo Vieira

Rodrigo Vieira

27/04/2010


 Caro Lobo, funcionou perfeitamente o script que voce me ensinou, realmente foi preciso colocar o id gerado pelo framework.

Ficou lindo, bacana, agora só tem um problema, ao ativar uma opção, é preciso desabilitar o required="true" do outro, e vice-versa, pois do jeito foi feito não deixa salvar e retorna a requiredMessage do componente, pesquisando na net descobri que atravéz de javascript nao dá pra fazer, que só atravéz de binding, é verdade ?

De resto ficou joia, funcionando do jeito que eu queria, tem apenas esse detalhe
GOSTEI 0
Rodrigo Vieira

Rodrigo Vieira

27/04/2010

Caro Lobo, funcionou perfeitamente o script que voce me ensinou, realmente foi preciso colocar o id gerado pelo framework.

Ficou lindo, bacana, agora só tem um problema, ao ativar uma opção, é preciso desabilitar o required="true" do outro, e vice-versa, pois do jeito foi feito não deixa salvar e retorna a requiredMessage do componente, pesquisando na net descobri que atravéz de javascript nao dá pra fazer, que só atravéz de binding,
isso é verdade ?

De resto ficou joia, funcionando do jeito que eu queria, tem apenas esse detalhe

GOSTEI 0
Henrique Weissmann

Henrique Weissmann

27/04/2010

Oi Rodrigo, neste caso, não sei como seria possivel desabilitar o required pelo Javascript, pois isto normalmente é feito pelo controlador. O que talvez possa ser feito é alguma validação adicionando um evento JavaScript ao método onsubmit, mas mesmo assim não é uma solução ideal. Ou então,o que você poderia fazer também é simplesmente não adicionar o atributo required=true na view e fazer a validação manualmente pelo próprio managed bean.
GOSTEI 0
Devmedia

Devmedia

27/04/2010

Rodrigo,
a resposta do consultor foi suficiente? Podemos encerrar o chamado?
GOSTEI 0
Rodrigo Vieira

Rodrigo Vieira

27/04/2010

Sim, podemos fechar o chamado.
GOSTEI 0
POSTAR