Introdução

Fala galera, beleza?

Esse é o meu primeiro post técnico, e nele vamos criar um formulário, sem a necessidade de back-end para fazer o envio dos dados preenchidos.

Abaixo um exemplo de como ficará nosso formulário:

Jekyll e Formspree

Uma coisa que me incomodava quando estava desenvolvendo um site estático, era ter de utilizar algum framework javascript para reutilizar códigos html.

Por isso, ao refazer o meu site, busquei alternativas para resolver esse problema. Foi então que descobri o Jekyll.

O Jekyll é uma plataforma criada pelo pessoal do Github que tem como proposta dar a um site estático, features como includes, variáveis, laços de repetição, e muitas outras coisas. Isso tudo graças ao Liquid Template, uma linguagem de programação criada pela galera da Shopify.

Como o Liquid Template não dá suporte ao envio de formulário, tive que utilizar o Formspree como alternativa. Ele é um projeto open source que tem como proposta fazer exatamente o que eu precisava: envio de formulários em um site estático.

Existe uma forma padrão de utilizá-lo em que, após submetido o formulário, o usuário é redirecionado para uma página anti-spam, e em seguida os dados são enviados.

No entanto, se você já estudou um pouco de experiência do usuário, deve saber que tirar a pessoa da sua página nunca é uma boa solução. Por isso utilizaremos AJAX para fazer o envio dos dados, e uma animação em SVG como notificação de sucesso/falha.

Partes do tutorial

Como é muita coisa para ser abordada em apenas um tópico, vou divir o post em 3 partes:

Sem mais delongas, vamos começar! :D

Baixando o Boilerplate

Como o nosso foco é a parte do Javascript, criei um boilerplate para que você não precise se preocupar com o HTML e o CSS.

É só clonar esse repositório, e seguir os passos de instalação.

Estando tudo pronto, hora de por a mão na massa.

Função global

Vamos começar criando uma função auto executável para englobar todo o nosso código.

    (() => {

    })();

É um design pattern que tem como objetivo encapsular nossas variáveis e funções, para que elas não se encontrem no escopo global.

Serve como medida de segurança, evitando que elas sejam acessadas por terceiros, através das ferramentas de inspeção oferecidas pelos browsers, além de evitar que elas conflitem com variáveis de outras possiveis bibliotecas que possam ser importadas no site.

Variáveis

Agora vamos criar as váriaveis necessárias para manipular os elementos de UI.

    (() => {
        // DECLARANDO AS VARIÁVEIS REFERENTES À INTERFACE
        const container = document.querySelector(".container");
        const form = document.querySelector(".form");
        const fields = document.querySelectorAll(".input-field");
        const nameInput = document.querySelector("#name");
        const emailInput = document.querySelector("#email");
        const messageInput = document.querySelector("#message");
        const submitButton = document.querySelector("#submit-button");
    })();

Estrutura de funções

Em seguida, vamos criar a estrutura inicial do nosso script. Serão duas funções, uma que fará a validação em si, e uma para inicializarmos os eventos.

    // FUNÇÃO DE VALIDAÇÃO DO FORM
    const validateForm = () => {
    };

    // FUNÇÃO DE INICIALIZAÇÃO
    const init = () => {
    };

    init();

Validação com Expressões Regulares

Chegamos na parte mais interessante, as Expressões Regulares.

Expressões regulares são padrões utilizados para selecionar combinações de caracteres em uma string.

Ou seja, com elas conseguimos detectar determinados padrões dentro de uma string e, dependendo desse padrão, executar ou não uma função.

Alguns links de estudo:

Voltando ao nosso formulário, no campo de nome temos a seguinte expressão:

    nameRegexp = /[a-zA-Z\-'\s]+/;

Essa expressão tem como condicional a utilização de letras maiúsculas e minúsculas, e espaços

Já o campo de email é um pouco mais complexo:

    emailRegexp = /^[A-z0-9.-]{1,}@\w+\.[A-z]{2,3}(\.[a-z]{2})?$/;

Para melhor entendimento, fiz uma lista detalhando cada metacaractere:

  • ^ - Início da expressão;
  • [] - Classe de caracteres;
  • A-z0-9 - Alfanuméricos;
  • . - Qualquer caractere;
  • - - Caractere “-”,
  • {1,}@ - Apenas 1 caractere “@”;
  • \w+ - Forma abreviada dos alfanuméricos, sem limite de caracteres;
  • \. - Caractere “.”;
  • [A-z]{2,3} - Entre 2 e 3 caracteres de letras maiúsculas e minúsculas;
  • () - Grupo de caracteres;
  • \. - Caractere “.”;
  • [a-z]{2} - 2 caracteres de letras minúsculas;;
  • ? - Esse metacaractere indica que o grupo declarado anteriormente é opcional;
  • $ - Fim da expressão;

No campo de mensagem, colocamos como condicional que o campo não esteja vazio, podendo ser preenchido por qualquer outro caractere:

    msgRegexp = /.*\S.*/;

Caso tenha ficado alguma dúvida, abaixo um overview dos principais metacaracteres:

  • ^ - Início da linha;
  • $ - Fim da linha;
  • [a-Z] - Lista permitida;
  • {n} - Quantificador;
  • \c - Escape;
  • \w - Alfanuméricos;
  • + - Repetidor;
  • ()- Grupo;
  • \d - Apenas números;
  • \D - Não números;
  • \s - Espaços;
  • . - Qualquer caractere;
  • ? - Caractere anterior é opcional;
  • * - Caractere anterior repete uma ou mais vezes;

Veja lista completa

Voltando ao código, vamos setar nossas Expressões Regulares, e deixar nosso botão desabilitado por padrão:

    const nameRegexp = /[a-zA-Z\-'\s]+/;
    const emailRegexp = /^[A-z0-9.-]{1,}@\w+\.[A-z]{2,3}(\.[a-z]{2})?$/;
    const msgRegexp = /.*\S.*/;

    submitButton.disabled = false;

Agora criaremos uma função para fazer a validação do que for digitado pelo usuário.

Se o usuário digitou o que é esperado no campo de input, ele conseguirá habilitar o botão de submit e enviar os dados, caso contrário, mostraremos uma mensagem avisando para ele o que precisa ser digitado.

    // FUNÇÃO DE VALIDAÇÃO DO CAMPO
    const validateField = (regExp, field) => {
      if (regExp.test(field.value)) {
        field.classList.remove("is-danger");
        field.nextElementSibling.classList.add("is-hidden");
      } else {
        field.classList.add("is-danger");
        field.nextElementSibling.classList.remove("is-hidden");
        submitButton.disabled = true;
      }
    };

Agora vamos executar as funções de validação utilizando as variáveis declaradas lá em cima.

      validateField(nameRegexp, nameInput);
      validateField(emailRegexp, emailInput);
      validateField(msgRegexp, messageInput);

Por último, é só dispararmos a função de validação cada vez que um dos inputs for preenchido, e tirar o evento default do botão de envio do form.

    // FUNÇÃO DE INICIALIZAÇÃO
    const init = () => {
        fields.forEach(field => field.addEventListener("input", validateForm));
        
        submitButton.addEventListener("click", (evnt) => {
            evnt.preventDefault();
        });
    };

Bom pessoal, por enquanto ficamos por aqui.

Caso você tenha se perdido no meio do caminho, pode consultar o código dessa primeira parte.

Validação de formulário é algo primordial para qualquer front. Por mais que você não se interesse pelo tutorial como um todo, essa parte em específico com certeza será muito útil. Lembrando que, caso você não esteja trabalhando em um site estático, as informações também deve ser validadas no back-end.

Feedback, criticas e sugestões são muito bem vindas.

Valeu, e até a parte 2 :D.