Primeiro você precisa instalar o componente
react-validation-boo , presumo que você esteja familiarizado com o react e saiba como configurá-lo.
npm install reat-validation-booPara não falar muito, darei imediatamente um pequeno exemplo de código.
import React, {Component} from 'react'; import {connect, Form, Input, logger} from 'react-validation-boo'; class MyForm extends Component { sendForm = (event) => { event.preventDefault(); if(this.props.vBoo.isValid()) { console.log(' ', this.props.vBoo.getValues()); } else { console.log(' ', this.props.vBoo.getErrors()); } }; getError = (name) => { return this.props.vBoo.hasError(name) ? <div className="error">{this.props.vBoo.getError(name)}</div> : ''; }; render() { return <Form connect={this.props.vBoo.connect}> <div> <Input type="text" name="name" /> {this.getError('name')} </div> <button onClick={this.sendForm}> {this.props.vBoo.isValid() ? ' ': ' !!!'} </button> </Form> } } export default connect({ rules: () => ( [ ['name', 'required'], ] ), middleware: logger })(MyForm);
Vamos analisar esse código.
Vamos começar com a função
connect , passamos nossas regras de validação e outros parâmetros adicionais para ela. Ao chamar esse método, obtemos uma nova função na qual passamos nosso componente (
MyForm ) para que ele
receba os métodos necessários para trabalhar com a validação de formulário em
props .
Na função
render do nosso componente, retornamos o componente
Form que conectamos às regras de validação
connect = {this.props.connect} . Esse é um design necessário para o
Form saber como validar componentes aninhados.
<Input type = "text" name = "name" /> o campo de entrada que verificaremos, passamos as regras de verificação para
conectar -
se à propriedade de
regras . No nosso caso, esse
nome não deve estar vazio (
obrigatório ).
Também passamos o
middleware: logger para
conectar -
se para ver como a validação funciona no console.
Nos
props do nosso componente, temos um conjunto de funções:
- vBoo.isValid () - retorna true se todos os componentes de entrada foram validados
- vBoo.hasError (name) - retorna true se o componente com a propriedade name não for válido
- vBoo.getError (name) - para um componente com a propriedade name , retorna o texto do erro
Agora vamos complicar gradualmente, primeiro passaremos o idioma para a
conexão , para que possamos alterar as regras de validação dependendo do idioma e também adicionar campos e regras de validação adicionais.
import React, {Component} from 'react'; import {connect, Form, Input, InputCheckbox} from 'react-validation-boo'; class MyForm extends Component { sendForm = (event) => { event.preventDefault(); if(this.props.vBoo.isValid()) { console.log(' ', this.props.vBoo.getValues()); } else { console.log(' ', this.props.vBoo.getErrors()); } }; getError = (name) => { return this.props.vBoo.hasError(name) ? <div className="error">{this.props.vBoo.getError(name)}</div> : ''; }; render() { return <Form connect={this.props.vBoo.connect}> <div> <label>{this.props.vBoo.getLabel('name')}:</label> <Input type="text" name="name" /> {this.getError('name')} </div> <div> <label>{this.props.vBoo.getLabel('email')}:</label> <Input type="text" name="email" value="default@mail.ru" /> {this.getError('email')} </div> <div> <label>{this.props.vBoo.getLabel('remember')}:</label> <InputCheckbox name="remember" value="yes" /> {this.getError('remember')} </div> <button onClick={this.sendForm}> {this.props.vBoo.isValid() ? ' ': ' !!!'} </button> </Form> } } export default connect({ rules: (lang) => { let rules = [ [ ['name', 'email'], 'required', { error: '%name% ' } ], ['email', 'email'] ]; rules.push(['remember', lang === 'ru' ? 'required': 'valid']); return rules; }, labels: (lang) => ({ name: '', email: ' ', remember: '' }), lang: 'ru' })(MyForm);
Neste exemplo, a caixa de seleção
lembrar em russo deve ser instalada
necessária , mas em outros é sempre válida.
Também passamos os
rótulos da função
(lang) para
conectar , que retornam o nome dos campos em um formato legível.
Nos
props do seu componente, há uma função
getLabel (name) que retorna o valor passado para a função
labels , ou, se não houver esse valor, retorna
name .
Componentes principais do VBoo
Form ,
Input ,
InputRadio ,
InputCheckbox ,
Select ,
Textarea .
import React, {Component} from 'react'; import {connect, Form, Input, Select, InputRadio, InputCheckbox, Textarea} from 'react-validation-boo'; class MyForm extends Component { sendForm = (event) => { event.preventDefault(); if(this.props.vBoo.isValid()) { console.log(' ', this.props.vBoo.getValues()); } else { console.log(' ', this.props.vBoo.getErrors()); } }; getError = (name) => { return this.props.vBoo.hasError(name) ? <div className="error">{this.props.vBoo.getError(name)}</div> : ''; }; render() { return <Form connect={this.props.vBoo.connect}> <div> <label>{this.props.vBoo.getLabel('name')}:</label> <Input type="text" name="name" /> {this.getError('name')} </div> <div> <label>{this.props.vBoo.getLabel('email')}:</label> <Input type="text" name="email" value="default@mail.ru" /> {this.getError('email')} </div> <div> <label>{this.props.vBoo.getLabel('gender')}:</label> <Select name="gender"> <option disabled> </option> <option value="1"></option> <option value="2"></option> </Select> {this.getError('gender')} </div> <div> <div>{this.props.vBoo.getLabel('familyStatus')}:</div> <div> <InputRadio name="familyStatus" value="1" checked /> <label></label> </div> <div> <InputRadio name="familyStatus" value="2" /> <label></label> </div> <div> <InputRadio name="familyStatus" value="3" /> <label></label> </div> {this.getError('familyStatus')} </div> <div> <label>{this.props.vBoo.getLabel('comment')}:</label> <Textarea name="comment"></Textarea> {this.getError('comment')} </div> <div> <label>{this.props.vBoo.getLabel('remember')}:</label> <InputCheckbox name="remember" value="yes" /> {this.getError('remember')} </div> <button onClick={this.sendForm}> {this.props.vBoo.isValid() ? ' ': ' !!!'} </button> </Form> } } export default connect({ rules: () => ([ [ ['name', 'email'], 'required', { error: '%name% ' } ], ['email', 'email'], [['gender', 'familyStatus', 'comment', 'remember'], 'valid'] ]), labels: () => ({ name: '', email: ' ', gender: '', familyStatus: ' ', comment: '', remember: '' }), lang: 'ru' })(MyForm);
Regras de validação
Vamos ver como escrever nossas próprias regras de validação.
Para escrever uma regra, você deve criar uma classe que será herdada da classe
validadora .
import {validator} from 'react-validation-boo'; class myValidator extends validator { validate(name, value, params) { let lang = this.getLang(); let pattern = /^\d+$/; if(!pattern.test(value)) { let error = params.error || ' %name% %value%'; error = error.replace('%name%', name); error = error.replace('%value%', value); this.addError(error); } } } export default myValidator;
Agora conecte nosso validador ao formulário.
import myValidator from 'path/myValidator';
Para não registrar todas as suas regras de validação de cada vez, crie um arquivo separado onde elas serão registradas e conecte seus
validadores: `import 'file-validation`` . E se houver alguma regra especial para este formulário, os
validadores: Object.assign ({}, `import 'file-validation``, {...})Cenários
Considere os casos em que precisamos alterar as regras de validação, dependendo das ações executadas no formulário.
Por padrão, temos um script chamado
default , nas regras que podemos especificar em qual cenário realizar essa validação.
Se nenhum script for especificado, a validação será executada para todos os cenários.
rules = () => ([ [ 'name', 'required', { error: '%name% ' } ], [ 'name', 'myValidator', { scenario: ['default', 'scenario1'] } ], [ 'email', 'email', { scenario: 'scenario1' } ] ])
A função é passada através da propriedade
props do nosso componente:
- vBoo.setScenario (cenário) - define o script do cenário; ele pode ser uma sequência ou uma matriz, se houver vários scripts ativos ao mesmo tempo
- vBoo.getScenario () - retorna o script atual ou a matriz de scripts
- vBoo.hasScenario (name) - se este script está instalado agora, name string
Vamos adicionar um objeto de
cenários em nosso formulário, no qual armazenaremos todos os scripts possíveis;
verdadeiro ,
o script está ativo;
falso , não.
Além
das funções
addScenaries e
deleteScenaries que adicionarão e removerão scripts.
Se selecionarmos "coabitação" ou "casamento", adicionaremos um campo de comentário e, naturalmente, esse campo deverá ser validado apenas nesse caso, o
cenário casado com o cenário .
Se tivermos a caixa de seleção "Avançado" definida, adicionaremos campos adicionais que serão necessários, o script '
adição de cenário '.
import React, {Component} from 'react'; import {connect, Form, Input, Select, InputRadio, InputCheckbox, Textarea} from 'react-validation-boo'; class MyForm extends Component { constructor() { super(); this.scenaries = { 'scenario-married': false, 'scenario-addition': false } } changeScenaries(addScenaries = [], deleteScenaries = []) { addScenaries.forEach(item => this.scenaries[item] = true); deleteScenaries.forEach(item => this.scenaries[item] = false); let scenario = Object.keys(this.scenaries) .reduce((result, item) => this.scenaries[item]? result.concat(item): result, []); this.props.vBoo.setScenario(scenario); } addScenaries = (m = []) => this.changeScenaries(m, []); deleteScenaries = (m = []) => this.changeScenaries([], m); sendForm = (event) => { event.preventDefault(); if(this.props.vBoo.isValid()) { console.log(' ', this.props.vBoo.getValues()); } else { console.log(' ', this.props.vBoo.getErrors()); } }; getError = (name) => { return this.props.vBoo.hasError(name) ? <div className="error">{this.props.vBoo.getError(name)}</div> : ''; }; changeFamilyStatus = (event) => { let val = event.target.value; if(val !== '1') { this.addScenaries(['scenario-married']) } else { this.deleteScenaries(['scenario-married']); } }; changeAddition = (event) => { let check = event.target.checked; if(check) { this.addScenaries(['scenario-addition']) } else { this.deleteScenaries(['scenario-addition']); } }; getCommentContent() { if(this.props.vBoo.hasScenario('scenario-married')) { return ( <div key="comment-content"> <label>{this.props.vBoo.getLabel('comment')}:</label> <Textarea name="comment"></Textarea> {this.getError('comment')} </div> ); } return ''; } getAdditionContent() { if(this.props.vBoo.hasScenario('scenario-addition')) { return ( <div key="addition-content"> <label>{this.props.vBoo.getLabel('place')}:</label> <Input type="text" name="place" /> {this.getError('place')} </div> ); } return ''; } render() { return <Form connect={this.props.vBoo.connect}> <div> <label>{this.props.vBoo.getLabel('name')}:</label> <Input type="text" name="name" /> {this.getError('name')} </div> <div> <label>{this.props.vBoo.getLabel('email')}:</label> <Input type="text" name="email" value="default@mail.ru" /> {this.getError('email')} </div> <div> <label>{this.props.vBoo.getLabel('gender')}:</label> <Select name="gender"> <option disabled> </option> <option value="1"></option> <option value="2"></option> </Select> {this.getError('gender')} </div> <div> <div>{this.props.vBoo.getLabel('familyStatus')}:</div> <div> <InputRadio name="familyStatus" value="1" checked onChange={this.changeFamilyStatus} /> <label></label> </div> <div> <InputRadio name="familyStatus" value="2" onChange={this.changeFamilyStatus} /> <label></label> </div> <div> <InputRadio name="familyStatus" value="3" onChange={this.changeFamilyStatus} /> <label></label> </div> {this.getError('familyStatus')} </div> {this.getCommentContent()} <div> <label>{this.props.vBoo.getLabel('addition')}:</label> <InputCheckbox name="addition" value="yes" onChange={this.changeAddition} /> {this.getError('addition')} </div> {this.getAdditionContent()} <button onClick={this.sendForm}> {this.props.vBoo.isValid() ? ' ': ' !!!'} </button> </Form> } } export default connect({ rules: () => ([ [ ['name', 'gender', 'familyStatus', 'email'], 'required', { error: '%name% ' } ], ['email', 'email'], [ 'comment', 'required', { scenario: 'scenario-married' } ], ['addition', 'valid'], [ 'place', 'required', { scenario: 'scenario-addition' } ], ]), labels: () => ({ name: '', email: ' ', gender: '', familyStatus: ' ', comment: '', addition: '', place: '' }), lang: 'ru' })(MyForm);
Para não tornar o artigo muito grande, continuarei no próximo, onde escreverei como criar meus próprios componentes (por exemplo, um calendário ou inputSearch) e validá-los, como se relacionar com redux e muito mais.