UNPKG

form-validator-la

Version:

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

414 lines (332 loc) 16.8 kB
# form-validator-la ### Este README contem _anchor links_ para uma melhor experiência leia este documento através do [git-hub](https://github.com/lucas-almeida026/form-validator-la/blob/main/README.md 'Open with GitHub') form-validator-la é um validador de formulário HTML feito em javascript para front-end. Os exemplos serão feitos em React. ## Instalação ```bash npm i form-validator-la ``` ## Importando o pacote <!-- Para fazer validações em Node use o [pacote para Nodejs] --> ```javascript 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](#Implementando-onSubmit) 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](#Implementando-onLeaveInput) 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 ```javascript 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](#Validações-personalizadas). 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](#Implementando-passwordComplexity)) #### 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](#Criando-o-objeto-de-configurações-de-validação) ### 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 ```javascript 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 <value> e retorna um expressão lógica Exemplo: ```javascript 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: ```javascript 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: ```javascript 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: ```javascript 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: ```javascript // 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: ```javascript // 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: ```javascript // 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: ```javascript // 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> </> ) } ```