JQuery / JQuery Validation / Síncrono E Assíncrono / CPF único No Banco De Dados / Ajax Síncrono Com JQuery

Salve pessoal.

Hoje trago um artigo pesado e extenso, mas acredito que vá ajudar o pessoal que precisar em várias frentes. Vou Tratar aqui de JQuery, JQuery Validation, a diferença entre síncrono e assíncrono, como fazer ajax síncrono usando JQuery e também soluções para problemas em um dia de trabalho no mundo do desenvolvimento.

Bom, que o JQuery é um dos frameworks mais usados para javascript e que facilita muito a sua vida você já deve saber. E que o plugin para JQuery, JQuery Validation, é uma excelente maneira de validar seus formulários do lado cliente, você também deveria saber.

Veja um exemplo:

<script type="text/javascript" src="jquery.js"></script>
<script type="text/javascript" src="jquery.validate.js"></script>
<script type="text/javascript">
    
function init()
{
    $("#form").validate({
        rules:
        {
            nome:{required: true},
            senha:{required: true, minlength: 5}
                }
    });
}

$(document).ready(init);
    
</script>

</head>
<body>

<form id="form">
    
    <p>
        <label for="nome">Nome</label>
        <input type="text" name="nome" id="nome" />
    </p>
    
    <p>
        <label for="senha">Senha</label>
        <input type="password" name="senha" id="senha" />
    </p>
    
</form>

</body>

Com essas poucas linhas você já tem um formulário com campo obrigatório para nome e campo obrigatório para senha exigindo um mínimo 5 caractéres.Ao não seguir qualquer uma das regras, o plugin insere uma Label com uma mensagem de erro.

Você tem opções para personalizar essa mensagem, além de outras várias opções oferecidas pelo plugin.
Você pode dar uma conferida nessas opções pela documentação e exemplos no site oficial do plugin aqui.

Primeiro Problema

O plugin JQuery Validation é gringo; Internacional se você preferir assim dizer.
Na sua condição de estrangeiro, ele não conhece o que é CPF.
Ele não tem um método para entrada e validação de CPF, o que é muito comum nos formulários de cadastro aqui no Brasil.

Por sorte, o JQuery validation tem uma maneira muito fácil de você inserir novos métodos a ele.
Com uma rápida busca na internet chegamos em vários blogs que nos trazem a solução, como é o caso do TidBits escrito pelo Danilo Augusto, que falou sobre isso em seu post Coleção de métodos para o plugin validate do Jquery.

Primeiro vamos adicionar um campo para o CPF.
Vamos também separar o arquivo .js para ficar mais organizado a coisa toda, separando o que é Html do que é javascript.

Nosso Html vai ficar assim:

<script src="jquery.js" type="text/javascript"></script>
<script src="jquery.validate.js" type="text/javascript"></script>
<!-- default.js será o arquivo separado do javaScript -->
<script src="default.js" type="text/javascript"></script>

<form id="form">
        
    <p>
        <label for="nome">Nome</label>
        <input type="text" name="nome" id="nome" />
    </p>
    
    <p>
        <label for="senha">Senha</label>
        <input type="password" name="senha" id="senha" />
    </p>

    <p>
        <label for="cpf">CPF</label>
        <input type="text" name="cpf" id="cpf" />
    </p>
    
</form>

Ok, adicionamos o Input para o CPF em nosso HTML.
Agora vamos adicionar o método para o Jquery Validation no nosso arquivo default.js, seguindo o exemplo que pegamos no Blog do Danilo.

function init()
{
    $("#form").validate({
        rules:
        {
            nome:{required: true},
            senha:{required: true, minlength: 5}
           }
    });
}

jQuery.validator.addMethod("verificaCPF", function(value, element) {
value = value.replace('.','');
value = value.replace('.','');
cpf = value.replace('-','');
while(cpf.length < 11) cpf = "0"+ cpf;
var expReg = /^0+$|^1+$|^2+$|^3+$|^4+$|^5+$|^6+$|^7+$|^8+$|^9+$/;
var a = [];
var b = new Number;
var c = 11;
for (i=0; i<11; i++){
    a[i] = cpf.charAt(i);
    if (i < 9) b += (a[i] * --c);
}
if ((x = b % 11) < 2) { a[9] = 0 } else { a[9] = 11-x }
b = 0;
c = 11;
for (y=0; y<10; y++) b += (a[y] * c--);
if ((x = b % 11) < 2) { a[10] = 0; } else { a[10] = 11-x; }
if ((cpf.charAt(9) != a[9]) || (cpf.charAt(10) != a[10]) || cpf.match(expReg)) return false;
return true;
}, "Informe um CPF válido.");

$(document).ready(init);

Agora falta chamar o método para o seu campo.
Para isso adicione a seguinte validação no seu código javascript:

$("#form").validate({
    rules:
    {
        nome:{required: true},
        senha:{required: true, minlength: 5},
        cpf:{required: true, verificaCPF: true}
       }
});

Repare:
Chamamos o método verificaCPF, e passamos o valor que queremos, no caso, true para que seja um CPF válido.
Faça seus testes.

Segundo Problema

Legal! Temos o formulário validando, inclusive com um campo de CPF, sem muito trabalho pois estamos contando com o JQuery Validation. Mas então nos surgi outro problema. No seu banco de dados você tem um campo onde CPF tem de ser único.

E para ajudar seu usuário, além de mostrar se o CPF é válido ou não, você quer mostrar se é um CPF cadastrado ou não.
E então, como fazemos ?

Para pesquisas no banco de dados sem refresh na página a resposta é fácil não? Ajax!
Mas como juntar isso no Jquery validation?

Você conhecendo a facilidade do Ajax no Jquery, pode sair logo de cara transformando o seu método de validação de CPF para o seguinte:

jQuery.validator.addMethod("verificaCPF", function(value, element) {
    
value = value.replace('.','');
value = value.replace('.','');
cpf = value.replace('-','');

while(cpf.length < 11) cpf = "0"+ cpf;
var expReg = /^0+$|^1+$|^2+$|^3+$|^4+$|^5+$|^6+$|^7+$|^8+$|^9+$/;
var a = [];
var b = new Number;
var c = 11;

for (i=0; i<11; i++)
{
    a[i] = cpf.charAt(i);
    if (i < 9) b += (a[i] * --c);
}

if ((x = b % 11) < 2) { a[9] = 0 } else { a[9] = 11-x }

b = 0;
c = 11;

for (y=0; y<10; y++) b += (a[y] * c--);

if ((x = b % 11) < 2) { a[10] = 0; } else { a[10] = 11-x; }

if ((cpf.charAt(9) != a[9]) || (cpf.charAt(10) != a[10]) || cpf.match(expReg)) return false;

var verifica = false;
$.get('verificaCpf.php', {cpf : cpf}, function(data){
    if(data == 0) verifica = true;
});

if(!verifica) return false;

return true;
}, "CPF inválido ou já cadastrado!");

Vamos ver o que foi feito aqui. Acompanhe da linha 30 em diante.
Adicionamos uma variável dentro do nosso método chamada “verifica”, e definimos o valor de false para ela.

Em seguida fazemos uma chamada para um arquivo PHP através de Ajax.
Esse arquivo PHP deve fazer uma consulta no seu banco de dados pelo CPF digitado.
Por ser algo simples de fazer e para não estender ainda mais esse post ,não vou tratar desse código PHP aqui.

Para entendimento, basta saber que nosso código PHP retorna o número de linhas onde encontrou aquele CPF.
Esse valor vai vir para o javascript pela variável data.
Repare que é feito uma comparação na resposta do Ajax, que, caso o número de linhas encontradas no banco seja 0, mudamos a variável para true. E fim do Ajax.

Em seguida, verificamos a variável “verifica”.
Se ela for diferente de verdadeira, o método verificaCPF retorna false e será acusado erro em seu formulário.

Ufa! Certo. Vamos testar?
Problemas acontecem não? Está sempre retornando erro.
O que está acontecendo?

Terceiro Problema

Vamos entender:
Seu código PHP é chamado. Ele vai lá no banco de dados, faz a consulta e está retonando o resultado.
Mas enquanto isso, o código javascript já continuou sua execução, e quando a resposta do ajax chegar, a execução do método terá acabado. Com isso ele vai retornar o valor que tinha na variável, false.

Isso acontece, pois o ajax padrão do JQuery, como foi usado acima, é assíncrono.
Você está se perguntando o que é isso? Vou tentar ser claro.
É o fato de não importar quando a resposta do ajax vai vir. Não precisar de sincronismo, compreende?

Porém veja que esse é exatamente o nosso problema aqui. Precisamos desse sincronismo.
Precisamos da resposta do nosso Ajax antes de continuar a execução do código.

Como fazer?
Vamos fazer o Ajax Síncrono.
A execução do javascript só pode continuar depois da resposta do ajax.

Procurando pela internet, achei alguns desenvolvedores falando que não é possível fazer ajax síncrono com JQuery. Isso não é verdade. É uma das primeiras coisas que encontramos na documentação.

Veja como fazer:

jQuery.ajax({
        url: 'verifica_cpf.php?cpf='+cpf,
        async: false,
        success: function(data) {
           if(data == 0) verifica = true; 
       }});

Passando o valor false para a propiedade async do ajax, temos nosso ajax síncrono.
Repare que o código segue o padrão JQuery e é fácil de entender.
Ao invés de passar as variáveis em uma propiedade, as adicionei no padrão GET diretamente na url.
Uma opção a isso seria usar a propiedade data.

Substituindo esse trecho de código no lugar do nosso ajax assíncrono anterior, temos nosso problema corrigido.

Uma observação importante, é você reparar que a execução dá página dá uma travada enquanto espera a resposta do javascript. Fique atento para não deixar de dar uma resposta em situações de erro ou sucesso. Caso contrário sua página vai ficar travada nesse ponto.

Quarto problema

Não não…brincadeira… hahaha

Legal! Acredito que chegamos finalmente ao final.
Dúvidas? Dicas para melhorar todo esse processo? Não deixem de comentar pessoal…
Grande Abraço!


Comments