form-validator-la

Validador de formulários em javascript para formúlários HTML - front-end

Usage no npm install needed!

<script type="module">
  import formValidatorLa from 'https://cdn.skypack.dev/form-validator-la';
</script>

README

form-validator-la

Este README contem anchor links para uma melhor experiência leia este documento através do git-hub

form-validator-la é um validador de formulário HTML feito em javascript para front-end. Os exemplos serão feitos em React.

Instalação

npm i form-validator-la

Importando o pacote

import validator from 'form-validator-la'

Introdução

Ao importar o pacote validator escolha a forma como vai validar o formulário existem duas formas disponíveis onSubmit e onLeaveInput.

A função onSubmit valida o formulário a partir da captura do evento de submissão do mesmo, veja como implementar validator.doValidations().onSubmit() aqui

A função onLeaveInput valida o formulário a partir da captura do evento onFocusOut dos inputs do formulário, veja como implementar validator.doValidations().onLeaveInput aqui

As duas funções descritas acima retornam um Observable, basta se increver no observable retornado para ter acesso aos erros de validação do formulário.

Definindo as configurações de validação

Para validar um formulário é necessário criar um objeto com as configurações de validação contendo um objeto de regras (OBRIGATÓRIO) e um dicionário (OPCIONAL) e depois chamar o método doValidations para receber o observable.

  • rules: Define as regras de validação

  • dictionary (OPCIONAL): Define o dicionário para traduzir o nome do input, usado para personalizar a mensagem de erro

Criando o objeto de configurações de validação

const validationConfigs = {
  rules: {
    userName: [validator.required(), validator.minLength(3), validator.maxLength(50)],
    userEmail: [validator.required(), validator.isEmail(), validator.minLength(4), validator.maxLength(50)],
  },
  dictionary: {
    userName: 'Nome',
    userEmail: 'Email'
  }
}

Sobre as regras de validação

Existem 6 regras de validações pré-definidas, mas há a possibilidade de se criar validações personalizadas, veja como aqui.

As validações pré-definidas são:

  • required: torna o campo obrigatório
  • minLength: estabelece um número mínimo de caracteres para o campo
  • maxLength: estabelece um número máximo de caracteres para o campo
  • isEmail: verifica se o valor preenchido é um email (não verifica se o email é válido, apenas se é um email)
  • isJSON: verifica se o valor preenchido é um JSON,
  • passwordComplexity: estabelece regras para a criação de senhas (veja como implementar esta validação aqui)

IMPORTANTE:

As funções são executadas na ordem de declaração (da esquerda para a direita), portanto prefira começar pela validação required.

Para que as funções minLength e maxLength funcionem corretamente deve-se passar o valor mínimo e o valor máximo, respectivamente, na criação das regras, como no exemplo do tópico anterior

Validações combinadas

Caso seja necessário realizar a comparação do valor de um campo com o valor de outro, como por exemplo verificar se a valor do campo <senha> é igual ao valor de <repetirSenha>, utilize a função doCombinedValidation.

doCombinedValidation recebe uma referência de um input HTML (obrigatório) e retorna um objeto com três opções:

  • equalsTo: verifica se o valor do primeiro input é exatamente igual ao valor do segundo input
  • differentOf: verifica se o valor do primeiro input é diferente do valor do segundo input
  • includedIn: verifica se o valor do segundo input contem o valor do primeiro input, esta função recebe um segundo parâmetro chamado <flag>
    • Flag pode assumir 3 valores pré-definidos, por padrão caso não seja especificada a comparação será feita usando a flag "literal", Os valores são:
      • literal: compara os dois valores literalmente, sem nenhum tratamento
      • email: indicado para comparações envolvendo campos de email, compara os valores ignorando o host do email
      • treated: compara os dois valores desconsiderando espaçamentos laterais e letras maiúsculas

Depois de selecionar umas das 3 opções ['equalsTo', 'differentOf', 'includedIn'] passe a referência do segundo input, o input que servirá como base para a comparação.

Exemplos de validação combinada

const nameInvalid = validator
  .doCombinedValidation(document.getElementById('name'))
  .equalsTo(document.getElementById('lastName'))
// Verifica se o valor do input <name> é igual ao valor do input <lastName>

const passwordWithEmail = validator
  .doCombinedValidation(document.getElementById('email'))
  .includedIn(document.getElementById('password'), validator.includedInFlags.email)
// Verifica se o valor do input <password> contem o valor do input <email> ignorando espaços laterais e letter case e a terminação do email ["@gmail.com", "@hotmail.com", etc.]

const passwordWithName = validator
  .doCombinedValidation(document.getElementById('name'))
  .includedIn(document.getElementById('password'), validator.includedInFlags.treated)
// Verifica se o valor do input <password> contem o valor do input <name> ignorando espaços laterais e letter case

const equalPasswords = validator
  .doCombinedValidation(document.getElementById('password'))
  .differentOf(document.getElementById('repeatPassword'))
// Verifica se o valor do input <password> é diferente do valor do input <repeatPassword>

Validações personalizadas

Caso as validações pré-definidas não sejam suficientes para o seu problema, use o método createCustomValidation() para criar facilmente sua própria regra de validação. Obs.: Não é possível criar novas regras para validações combinadas.

createCustomValidation recebe dois parâmetros:

  • funcName: O nome da função
  • expression: Uma função que recebe um valor e retorna um expressão lógica

Exemplo:

const myValidation = validator.createCustomValidation('myValidation', (value) => value === 'foo')
// No exemplo acima <myValidation> verifica se o valor digitado no campo é exatamente igual a "foo"

Objeto de erro

Todas as validações retornam um objeto, caso não haja nenhum erro, de acordo com as regras definidas, o objeto retornado será um objeto vazio: {}. Se houver um ou mais erros será retornado um objeto com o seguinte formato:

{
  error: true,
  message: <Mensagem informando o campo que está errado e qual erro foi apontado>,
  raw: [<nomeDoCampo>, <erroApontado>]
}

Durante a validação do formuçário, caso a função encontre um erro de validação ela imediatamente retornará o erro, sendo assim os erros são apresentados seguindo a ordem de declaração.

Sobre o valor raw do objeto de erro

Caso a mensagem padrão não seja útil para o seu caso, utilize o valor raw do objeto de erro para compor sua própria mensagem.

Exemplo:

let myMessage
switch (objError.raw[1]){
  case 'myValidation':
    myMessage = `O campo ${objError.raw[0]} deve ter valor exatamente igual a "foo"`
    return

  default:
    return
}

Implementando passwordComplexity

Como dito anteriormente passwordComplexity pode ser utilizada para verificar a complexidade de uma senha, esta função recebe dois parâmetros na inicialização:

  • template: Valor do tipo string, é o que define o mínimo de complexidade de senha aceita
  • configs (OPCIONAL): Um objeto com duas propriedades que por padrão são setadas com true (permitido):
    • allowSpaces: permite ou bloqueia o uso do caracter <space> em uma senha
    • allowKeyboardSequences: permite ou bloqueia o uso de sequências de teclado como "asd", "123", "!@#", etc.

A propriedade template deve ser do tipo string e deve conter 4 caracteres de comprimento. Para formar o template utilize uma combinação dos caracteres reservados ['a', 'A', '1', '*', '_'] cada um possui um significado:

  • 'a': torna obrigatório o uso de letras minúsculas
  • 'A': torna obrigatório o uso de letras maiúsculas
  • '1': torna obrigatório o uso de números
  • '*': torna obrigatório o uso de caracteres especiais
  • '_': NÃO torna obrigatório

Exmplo de utilização:

const template = 'aA1_' //Este template torna obrigatório o uso de letras minúsculas, letras maiúsculas e números
const configs = {
  allowSpaces: false
}
const rules = {
  input1: [validator.required(), validator.passwordComplexity(template, configs)]
}

Um pouco mais sobre templates:

const template = '____' // Não torna nada obrigatório
const template = 'a___' // Tona obrigatório o uso de letras minúsculas
const template = 'aA__' // Tona obrigatório o uso de letras minúsculas e letras maiúsculas
const template = 'aA1_' // Tona obrigatório o uso de letras minúsculas, letras maiúsculas e números
const template = 'aA1*' // Tona obrigatório o uso de letras minúsculas, letras maiúsculas, números e caracteres especiais
const template = '1*Aa' // Tona obrigatório o uso de números, caracteres especiais, letras maiúsculas e letras minúsculas

// Como visto no exmplo acima alterar a ordem dos caracteres do template altera a ordem de verificação e a mensagem de erro

const template = 'a111' // Gera uma exceção, pois um template não pode ter caracteres de e obrigatoriedade repetidos. (O único caractere que pode ser repetido é o underline "_")

Implementando onSubmit

Ao utilizar a função onSubmit é necessário capturar o evento onSubmit no elemento

Implementação reduzida:

// Função para validar o formulário
const onSubmitForm = event => {
  event.preventDefault()
  const rules = {
    name: [validator.required(), validator.minLength(3), validator.maxLength(20)],
    email: [validator.required(), validator.isEmail()]
  }

  validator
    .doValidations({rules})
    .onSubmit(document.getElementById('form'))
    .subscribe(res => {
      if(res.error) alert(res.error)
      goToOtherFunction()
    })
}

// Capturando o evento de submissão para alimentar a função acima
function App(){
  return (
    <>
      <form onSubmit={e => onSubmitForm(e)}>
        <input id="name" name="name" type="text" />
        <input id="email" name="email" type="text" />
        <input type="submit" />
      </form>
    </>
  )
}

Implementação extendida:

// Função para validar o formulário
const onSubmitForm = event => {
  event.preventDefault()
  const myValidation = validator.createCustomValidation('recaptcha', value => value === recaptcha.value)

  const rules = {
    name: [validator.required(), validator.minLength(3), validator.maxLength(20)],
    email: [validator.required(), validator.isEmail()],
    password: [validator.required(), validator.minLength(8), validator.maxLength(64), validator.passwordComplexity('aA1_', {allowSpaces: false})],
    repeatPassword: [validator.required(), validator.minLength(8), validator.maxLength(64), validator.passwordComplexity('aA1_', {allowSpaces: false})],
    recaptcha: [validator.required(), myValidation()]
  }

  const dictionary = {
    name: 'Nome',
    email: 'Email',
    password: 'Senha',
    repeatPassword: 'Repita a senha',
    recaptcha: 'reCAPTCHA'
  }

  validator
    .doValidations({rules, dictionary})
    .onSubmit(document.getElementById('form'))
    .subscribe(res => {
      if(res.error){
        alert(res.error)
      }else{
        const equalPasswords = validator
          .doCombinedValidation(document.getElementById('password'))
          .equalsTo(document.getElementById('repeatPassword'))

        const nameInPassword = validator
          .doCombinedValidation(document.getElementById('name'))
          .includedIn(document.getElementById('password'), validator.includedInFlags.treated)

        if(!equalPasswords){
          alert(msg)
            return
        }
        if(nameInPassword){
          alert(msg)
            return
        }
        goToOtherFunction()
      }
    })
}

// Capturando o evento de submissão para alimentar a função acima
function App(){
  return (
    <>
      <form onSubmit={e => onSubmitForm(e)}>
        <input id="name" name="name" type="text" />
        <input id="email" name="email" type="text" />
        <input id="password" name="password" type="password" />
        <input id="repeatPassword" name="repeatPassword" type="password" />
        <input id="recaptcha" name="recaptcha" type="text" />
        <input type="submit" />
      </form>
    </>
  )
}

Implementando onLeaveInput

Ao utilizar a função onLeaveInput é necessário capturar o evento onLoad do elemento.

Em ambientes single-page-application é necessário esperar o elemento carregar na página para então começar a observa-lo, para isso utilize a função validator.afterLoad().

validator.afterLoad() recebe dois parâmetros:

  • formId: do tipo string, serve para identificar o formulário a ser observado
  • callback: do tipo function, será invocada assim que o formulário for carregado

IMPORTNTE: Ao utilizar onLeaveInput certifique-se de que todos os inputs do formulário possuem as propriedades "name" e "id" e que as duas possuem o mesmo valor, caso contrário uma exceção será lançada.

Implementação reduzida:

// Função de validação do formulário
const validateForm = () => {
  const rules = {
    email: [validator.required(), validator.isEmail()],
    password: [validator.required(), validator.minLength(8)]
  }
  validator
    .doValidations({rules})
    .onLeaveInput(document.getElementById('form'))  
    .subscribe(res => {
      console.log(res)
    })
}

// Componente
function App(){
  return (
    <>
      <form id="form" onLoad={validator.afterLoad('form', validateForm)}>
        <input id="email" name="email" type="text" />
        <input id="password" name="password" type="password" />
        <input type="submit" />
      </form>
    </>
  )
}

Implementação extendida:

// Função de validação do formulário
const validateForm = () => {
const myValidation = validator.createCustomValidation('recaptcha', value => value === recaptcha.value)

const rules = {
  name: [validator.required(), validator.minLength(3), validator.maxLength(20)],
  email: [validator.required(), validator.isEmail()],
  password: [validator.required(), validator.minLength(8), validator.maxLength(64), validator.passwordComplexity('aA1_', {allowSpaces: false})],
  repeatPassword: [validator.required(), validator.minLength(8), validator.maxLength(64), validator.passwordComplexity('aA1_', {allowSpaces: false})],
  recaptcha: [validator.required(), myValidation()]
}

const dictionary = {
  name: 'Nome',
  email: 'Email',
  password: 'Senha',
  repeatPassword: 'Repita a senha',
  recaptcha: 'reCAPTCHA'
}

validator
  .doValidations({rules, dictionary})
  .onLeaveInput(document.getElementById('form'))
  .subscribe(res => {
    if(res.error){
      alert(res.error)
    }else{
      const equalPasswords = validator
        .doCombinedValidation(document.getElementById('password'))
        .equalsTo(document.getElementById('repeatPassword'))

      const nameInPassword = validator
        .doCombinedValidation(document.getElementById('name'))
        .includedIn(document.getElementById('password'), validator.includedInFlags.treated)

      if(!equalPasswords){
        alert(msg)
          return
      }
      if(nameInPassword){
        alert(msg)
          return
      }
      goToOtherFunction()
    }
  }

// Component
function App(){
  return (
    <>
      <form id="form" onLoad={validator.afterLoad('form', validateForm)}>
        <input id="name" name="name" type="text" />
        <input id="email" name="email" type="text" />
        <input id="password" name="password" type="password" />
        <input id="repeatPassword" name="password" type="password" />
        <input id="recaptcha" name="recaptcha" type="text" />
        <input type="submit" />
      </form>
    </>
  )
}