Na primeira parte (
Validação dos formulários React. Parte 1 ), descrevi como você pode trabalhar com o
formulário react-validate- agora, agora melhorarei o código. Retiramos o campo de entrada, dicas e erros em um bloco separado. E conecte
redux .
import React, {Component} from 'react'; import {connect as vBooConnect} from 'react-validation-boo'; import {connect as reduxConnect} from 'react-redux'; import {InputBlock, InputCheckboxBlock, InputRadioGroupBlock, TextareaBlock, SelectBlock} from '../form/default'; class MyForm extends Component { constructor() { super(); this.genderOptions = [ {value: '', label: ' ?'}, {value: 1, label: ''}, {value: 2, label: ''} ]; this.familyRadioList = [ {value: 1, label: ''}, {value: 2, label: ''}, {value: 3, label: ''} ]; } componentWillMount() { this.props.vBoo.subscribe('change:input', this.props.onChangeVBooInput); this.props.vBoo.subscribe('valid:form', this.props.onChangeVBooValid); } render() { let s = this.props.myStore.inputs; return <Form connect={this.props.vBoo.connect}> <InputBlock name="name" value={s.name} /> <InputBlock name="email" value={s.email} /> <SelectBlock name="gender" options={this.genderOptions} value={s.gender} /> <InputRadioGroupBlock name="familyStatus" items={this.familyRadioList} value={s.familyStatus} /> <TextareaBlock name="comment" value={s.comment} /> <InputCheckboxBlock name="addition" value="yes" checked={s.addition==='yes'} /> <button onClick={this.sendForm}> {this.props.vBoo.isValid() ? ' ': ' !!!'} </button> </Form> } } export default reduxConnect( store => ({ myStore: { // isValid: false, inputs: { email: 'test@mail.ru', gender: 0, familyStatus: 1 } } }), dispatch => ({ onChangeVBooInput: (input) => {...}, onChangeVBooValid: (isValid) => {...} }) )(vBooConnect({ rules: () => ([...]), labels: () => ({...}), })(MyForm));
Se a sua biblioteca não estiver instalada, você poderá baixá-la
git@github.com: tramak / react-validation-boo.gitE se você instalou o
react-validation-boo através do
npm install , atualize para a versão mais recente, no momento da publicação, é
2.2.4 .
Vamos agora criar os componentes
InputBlock ,
InputCheckboxBlock ,
InputRadioGroupBlock ,
TextareaBlock ,
SelectBlock .
Geralmente, existem vários modelos de exibição de formulários. Vamos criar uma pasta de
formulário nele.O padrão é o nosso design
padrão e criaremos componentes nele.
import React from 'react'; import {Input} from 'react-validation-boo'; class InputBlock extends Input { getError = () => { return this.props.vBoo.hasError() ? <div className="error">{this.props.vBoo.getError()}</div> : ''; }; render() { return ( <div> <label>{this.props.vBoo.getLabel()}:</label> <input {...this.props} onChange={this.change} onBlur={this.blur} /> {this.getError()} </div> ); } } export default InputBlock;
import React from 'react'; import {InputCheckbox} from 'react-validation-boo'; export default class InputCheckboxBlock extends InputCheckbox { getError = () => { return this.props.vBoo.hasError() ? <div className="error">{this.props.vBoo.getError()}</div> : ''; }; render() { return ( <div> <label>{this.props.vBoo.getLabel()}:</label> <input {...this.props} type="checkbox" onChange={this.change} /> {this.getError()} </div> ); } }
import React from 'react'; import {Textarea} from 'react-validation-boo'; export default class TextareaBlock extends Textarea { getError = () => { return this.props.vBoo.hasError() ? <div className="error">{this.props.vBoo.getError()}</div> : ''; }; render() { return ( <div> <label>{this.props.vBoo.getLabel()}:</label> <textarea {...this.props} onChange={this.change} onBlur={this.blur} /> {this.getError()} </div> ); } }
Vamos escrever um bloco para
Select, para que as opções possam ser passadas não apenas através de tags de opção, mas também através de uma matriz.
let genderOptions = [ {value: '', label: ' ?'}, {value: 1, label: ''}, {value: 2, label: ''} ]; <SelectBlock name="gender" options={genderOptions} /> <SelectBlock name="gender"> <option value=""> </option> <option value="1"></option> <option value="2"></option> </SelectBlock>
import React from 'react'; import {Select} from '../../../react-validation-boo/react-validation-boo/src/main'; export default class SelectBlock extends Select { componentWillMount() { this.children = this.props.options ? this.__getOptions(): this.props.children; } componentWillReceiveProps(nextProps) { let value = nextProps.value; if(this.props.value !== value) { this.props.vBoo.change(value); } } __getOptions() { return this.props.options.map((item) => { return <option value={item.value} disabled={item.disabled}>{item.label}</option>; }); } getError = () => { return this.props.vBoo.hasError() ? <div className="error">{this.props.vBoo.getError()}</div> : ''; }; render() { return ( <div> <label>{this.props.vBoo.getLabel()}:</label> <select {...this.props} onChange={this.change}> {this.children} </select> {this.getError()} </div> ); } }
Resta implementar o componente
InputRadioGroupBlock , vamos implementá-lo não com base nos existentes, mas a partir do zero. O componente de
formulário da biblioteca
react -validation-boo procura elementos com um campo de
nome entre seus descendentes e neles passa o objeto
vBoo nesse objeto por meio de
adereços e existem todos os métodos necessários para trabalhar com a validação de componentes. Para começar, escreveremos como usaremos o componente.
let familyRadioList = [ {value: 1, label: ''}, {value: 2, label: ''}, {value: 3, label: ''} ]; <InputRadioGroupBlock name="familyStatus" items={familyRadioList} />
import React, {Component} from 'react'; export default class InputRadioGroupBlock extends Component { state = { value: '' }; componentWillMount() { this.setState({value: this.props.value}); } componentDidMount() { this.props.vBoo.mount(this.state.value); } componentWillUnmount() { this.props.vBoo.unMount(); } componentWillReceiveProps(nextProps) { let value = nextProps.value; if(this.props.value !== nextProps.value) { this.props.vBoo.change(value); this.setState({value}); } } getOptions() { return this.props.items.map(item => { let checked = (this.state.value||'').toString()===(item.value||'').toString(); return <div key={item.value}> <input type="radio" name={this.props.name} value={item.value} checked={checked} onChange={this.change} /> <label>{item.label}</label> </div>; }); } change = (event) => { let value = event.target.value; this.props.onChange && this.props.onChange(event); this.props.vBoo.change(value); this.setState({value}); }; getError = () => { return this.props.vBoo.hasError() ? <div className="error">{this.props.vBoo.getError()}</div> : ''; }; render() { return ( <div> <div>{this.props.vBoo.getLabel()}:</div> {this.getOptions()} {this.getError()} </div> ); } }
Tudo isso está descrito na documentação do github, vou adicioná-lo.
Se você encontrar erros ou tiver sugestões de melhorias, escreva para o e-mail que eu refino, aprimore.
Nos comentários do artigo anterior, foi escrito que existem outras boas bibliotecas, sim, mas acho que esse não é um motivo para não escrever suas próprias decisões, refiná-las e melhorá-las quando houver vontade de escrever.