Ajax em Javascript

Atualmente, enviar formulários com Ajax, PHP e jQuery é moda entre desenvolvedores experientes e novatos, e não é por menos, além de economizar um novo carregamento de página, o usuário não perde o que já foi digitado no formulário, o que acontecia com os bons e velhos formulários em HTML e PHP.

Os prós de você aprender a tática que vou detalhar neste tutorial são:

  • Economia de recursos do servidor: Não é preciso um novo carregamento de página para enviar o formulário;
  • O usuário não perde o que foi digitado no formulário: Como não temos um novo carregamento de página, os dados que o usuário digitou permanecem no formulário;
  • Caso ocorra um erro de validação, apenas uma pequena parte da página é atualizada (para mostrar o erro ao usuário);
  • O código PHP morre ( exit ) assim que um erro de validação ocorrer;

Os contras são:

  • Você precisa saber o que fazer depois que o formulário for enviado;
  • Você deve tomar cuidado para o formulário não ser enviado milhares de vezes (cada clique no botão de submit gera um novo envio);
  • Você deve manipular os erros manualmente (caso contrário o usuário não vai saber o que está acontecendo por baixo dos panos).

Além disso, antes de continuar lendo este tutorial, saiba que vamos utilizar jQuery e o recurso que a biblioteca nos oferece sobre a utilização do Ajax. Se você quiser utilizar o Ajax nativo do JavaScript, veja nosso outro tutorial:

Então vamos lá!

A proposta

Para este tutorial, vamos simular a criação de um perfil de usuário bem simples.

Os campos do formulário serão:

  • Nome
  • Sobrenome
  • Sexo
  • Idade
  • Foto

Você pode adicionar mais campos se precisar, vou explicar como isso funciona no decorrer do tutorial.

A base de dados MySQL

Para salvar os dados dos nossos "clientes", vamos utilizar uma base de dados MySQL. No PHP vamos utilizar PDO para fazer a conexão com a base de dados e manipulação da base de dados.

O nome da base de dados será "clientes" e nossa tabela vai se chamar "dados_clientes".

Criação de base de dados e PDO fogem ao escopo do nosso tutorial, portanto, caso tenha dificuldades com esses assuntos, leia os artigos abaixo:

Nossa tabela terá os seguintes dados:

CREATE TABLE `clientes`.`dados_clientes` (
  `cliente_id` INT (11) NOT NULL AUTO_INCREMENT,
  `cliente_nome` VARCHAR (255),
  `cliente_sobrenome` VARCHAR (255),
  `cliente_idade` VARCHAR (255),
  `cliente_sexo` ENUM ('Masculino', 'Feminino', 'Outro'),
  `cliente_foto` VARCHAR (255),
  PRIMARY KEY (`cliente_id`)
) CHARSET = utf8 ;

Vamos utilizar charset UTF8, fique atento a este detalhe, caso contrário terá erros de codificação.

O formulário HTML

Nosso formulário irá utilizar os benefícios do HTML5, se você ainda não viu, recentemente escrevi um tutorial detalhando os novos recursos do HTML5 em formulários, veja no link abaixo:

Nosso formulário completo ficou assim:

<!DOCTYPE html>
<html>
<head>
	<meta charset="UTF-8">
	<title>Formulário HTML5 - Tutsup</title>
</head>
<body>

<form class="form_clientes" action="php/envia_clientes.php" method="post" enctype="multipart/form-data">

	<label for="cliente_nome"> Nome: </label> <br>
	<input type="text" class="cliente_nome" id="cliente_nome" name="cliente_nome" required> <br><br>
	
	<label for="cliente_sobrenome"> Sobrenome: </label> <br>
	<input type="text" class="cliente_sobrenome" id="cliente_sobrenome" name="cliente_sobrenome" required> <br><br>
	
	<label for="cliente_idade"> Idade: </label> <br>
	<input type="number" class="cliente_idade" id="cliente_idade" name="cliente_idade" required> <br><br>
	
	<label for="cliente_sexo"> Sexo: </label> <br>
	<select class="cliente_sexo" id="cliente_sexo" name="cliente_sexo" required>
		<option value=""></option>
		<option value="Masculino">Masculino</option>
		<option value="Feminino">Feminino</option>
		<option value="Outro">Outro</option>
	</select>
	<br><br>
	
	<label for="cliente_foto"> Nome: </label> <br>
	<input type="file" class="cliente_foto" id="cliente_foto" name="cliente_foto" required> <br><br>
	
	<input type="submit" value="Enviar">
	
</form>

</body>
</html>

É um formulário bem básico, porém, utilizamos todos os padrões necessários.

O PHP

Nossos arquivos de PHP deverão estar em uma pasta chamada php. Crie esta pasta e inclua os arquivos indicados nela.

pdo.php

O primeiro arquivo que vamos criar é o de conexão com a base de dados (PDO), veja:

<?php
/* Variáveis PDO */
$base_dados = 'clientes';
$usuario_bd = 'root';
$senha_bd   = '';
$host_db    = 'localhost';
$charset_db = 'utf8';
$conexao_pdo = null;
 
/* Concatenação das variáveis para detalhes da classe PDO */
$detalhes_pdo  = 'mysql:host=' . $host_db;
$detalhes_pdo .= ';dbname='. $base_dados;
$detalhes_pdo .= ';charset='. $charset_db;
 
// Tenta conectar
try {
    // Cria a conexão PDO com a base de dados
    $conexao_pdo = new PDO($detalhes_pdo, $usuario_bd, $senha_bd);
} catch (PDOException $e) {
    // Se der algo errado, mostra o erro PDO
    print "Erro: " . $e->getMessage() . "<br/>";
    
    // Mata o script
    die();
}
?>

Lembre-se que isso já foi detalhado na aula: PDO em PHP.

envia_clientes.php

Nosso arquivo que vai enviar os dados para a base de dados MySQL é o envia_clientes.php, vamos validar os dados enviados passo a passo para você entender.

Nossa verificação será feita ao contrário, ou seja, ao invés de verificar se algo está correto, vamos verificar se algo NÃO está correto. Caso algo não passe na validação, matamos o script PHP com exit.

A primeira verificação é para saber se os dados foram enviados.

// Se não postar nada
if ( ! isset( $_POST ) || empty( $_POST ) ) {
	
	// Mensagem para o usuário
	echo 'Nada a publicar!';
	
	// Mata o script
	exit;
}

Em nossa segunda verificação, vamos ver se existe algum campo em branco.

// Verifica campos em branco
foreach ( $_POST as $chave => $valor ) {
	// Cria as variáveis dinamicamente
	$$chave = $valor;
	
	// Verifica campos em branco
	if ( empty( $valor ) ) {
		// Mensagem para o usuário
		echo 'Existem campos em branco.';
		
		// Mata o script
		exit;
	}
}

Agora vamos verificar se todas as variáveis que precisamos estão definidas:

// Verifica se todas as variáveis estão definidas
if (  
	   ! isset( $cliente_nome      )  
	|| ! isset( $cliente_sobrenome ) 
	|| ! isset( $cliente_idade     )
	|| ! isset( $cliente_sexo      )
) {
	// Mensagem para o usuário
	echo 'Existem variáveis não definidas.';

	// Mata o script
	exit;
}

Agora vamos enviar a imagem para uma pasta chamada imagens. Não vou validar a imagem nem entrar em detalhes sobre o envio, isso fica para uma próxima aula. Mesmo assim, segue o código:

// A imagem
$imagem = isset( $_FILES['cliente_foto'] ) ? $_FILES['cliente_foto'] : null;

// Verifica se existe imagem
if ( empty( $imagem ) ) {
	// Mensagem para o usuário
	echo 'Envie sua foto.';
	
	// Mata o script
	exit;
}

// Dados da imagem
$imagem_tmp   = $imagem['tmp_name'];
$nome_imagem  = $imagem['name'];
$diretorio    = '../imagens/';
$envia_imagem = $diretorio . $nome_imagem;

// Envia a foto
if ( ! move_uploaded_file( $imagem_tmp , $envia_imagem ) ) {
	// Mensagem para o usuário
	echo 'Erro ao enviar foto.';
	
	// Mata o script
	exit;
}

Agora podemos incluir nosso arquivo de conexão PDO:

// Inclui o arquivo de conexão
include('pdo.php');

E enviar os dados para a base de dados:

// Prepara o envio
$prepara = $conexao_pdo->prepare("
	INSERT INTO `clientes`.`dados_clientes` (
		`cliente_nome`,
		`cliente_sobrenome`,
		`cliente_idade`,
		`cliente_sexo`,
		`cliente_foto`
	) 
	VALUES
	( ?, ?, ?, ?, ? )
");

// Envia
$verifica = $prepara->execute(
	array(
		$cliente_nome,
		$cliente_sobrenome,
		$cliente_idade,
		$cliente_sexo,
		$envia_imagem
	)
);

Para verificar se os dados foram incluídos com sucesso, simplesmente faça:

if ( $verifica ) {
	echo 'OK';
	
	// Mata o script
	exit;
} else {
	echo 'Erro ao enviar dados.';
	
	// Mata o script
	exit;
}

Pronto, a parte mais complicada passou, agora vamos ver o Ajax e jQuery.

jQuery / Ajax

Agora vamos melhorar um pouco nosso formulário com jQuery e Ajax.

A primeira coisa a fazer, é baixar o jQuery e adicionar o script em nosso HTML. Faça o download em:

Vamos utilizar a versão 1.11.1.

Incluindo os arquivos .js no HTML

Além do jQuery, vamos criar nosso próprio script, chamado scripts.js. Tanto o arquivo jquery-1.11.1.min.js quanto scripts.js estarão em uma pasta chamada js.

Depois de colocar todos os arquivos na pasta js, inclua o seguinte no cabeçalho do seu HTML (entre <head> e </head>).

<script src="js/jquery-1.11.1.min.js"></script>
<script src="js/scripts.js"></script>

Capturando o submit do formulário

Agora vamos escrever todo o nosso código dentro do arquivo scripts.js. Para capturar e anular o submit do formulário, faça o seguinte:

// Inicia o jQuery
$(function(){
	$('.form_clientes').submit(function(){
		
		// O restante virá aqui
		
		// Anula o envio convencional
		return false;
	});
});

Perceba que agora podemos manipular todos os dados do formulário, e enviar com Ajax, já que agora a página não será mais atualizada.

Para nosso exemplo, vamos fazer milhares de verificações (todas testadas por mim), veja abaixo:

// Inicia o jQuery
$(function(){

	// Cria uma variável que vamos utilizar para verificar se o
	// formulário está sendo enviado
	var enviando_formulario = false;
	
	// Captura o evento de submit do formulário
	$('.form_clientes').submit(function(){
		
		// O objeto do formulário
		var obj = this;
		
		// O objeto jQuery do formulário
		var form = $(obj);
		
		// O botão de submit
		var submit_btn = $('.form_clientes :submit');
		
		// O valor do botão de submit
		var submit_btn_text = submit_btn.val();

		// Dados do formulário
		var dados = new FormData(obj);
		
		// Retorna o botão de submit ao seu estado natural
		function volta_submit() {
			// Remove o atributo desabilitado
			submit_btn.removeAttr('disabled');
			
			// Retorna o texto padrão do botão
			submit_btn.val(submit_btn_text);
			
			// Retorna o valor original (não estamos mais enviando)
			enviando_formulario = false;
		}
		
		// Não envia o formulário se já tiver algum envio
		if ( ! enviando_formulario  ) {		
		
			// Envia os dados com Ajax
			$.ajax({
				// Antes do envio
				beforeSend: function() {
					// Configura a variável enviando
					enviando_formulario = true;
					
					// Adiciona o atributo desabilitado no botão
					submit_btn.attr('disabled', true);
					
					// Modifica o texto do botão
					submit_btn.val('Enviando...');
					
					// Remove o erro (se existir)
					$('.error').remove();
				}, 
				
				// Captura a URL de envio do form
				url: form.attr('action'),
				
				// Captura o método de envio do form
				type: form.attr('method'),
				
				// Os dados do form
				data: dados,
				
				// Não processa os dados
				processData: false,
				
				// Não faz cache
				cache: false,
				
				// Não checa o tipo de conteúdo
				contentType: false,
				
				// Se enviado com sucesso
				success: function( data ) {	
					volta_submit();
					
					// Se os dados forem enviados com sucesso
					if ( data == 'OK' ) {
						// Os dados foram enviados
						// Aqui você pode fazer o que quiser
						alert('Dados enviados com sucesso');
					} else {
						// Se não, apresenta o erro perto do botão de envio
						submit_btn.before('<p class="error">' + data + '</p>');
					}
				},
				// Se der algum problema
				error: function (request, status, error) {
					// Volta o botão de submit
					volta_submit();
					
					// E alerta o erro
					alert(request.responseText);
				}
			});
		}
		
		// Anula o envio convencional
		return false;
		
	});
});

Minha maior preocupação é o cliente enviar o formulário mais de uma vez quando o servidor estiver lento, por isso, tivemos tantas verificações.

Vídeo tutorial

Eu já criei um vídeo tutorial detalhando como enviar formulário com jQuery e Ajax, porém, era um pouco diferente, pois, enviamos apenas texto. Neste caso, ao invés de utilizarmos "FormData", utilizamos serialize (bem mais simples).

Mesmo assim, assista ao vídeo abaixo, pode tirar algumas dúvidas que você venha a ter.

Espero que ajude.

Download

Caso queira baixar o formulário criado nessa aula (com base de dados e tudo mais), basta clicar no link abaixo:

Você precisará importar a base de dados para seu servidor MySQL.

Concluindo

Este tutorial detalha bastante tudo o que costumo utilizar quando envio formulários com Ajax, porém, o lado do PHP ainda faltam algumas validações, como a validação da imagem, por exemplo.

Ainda vamos escrever muitos tutoriais para que você entenda melhor o processo, porém, se tiver dúvidas é só perguntar.