📜 ⬆️ ⬇️

Validation of React Forms. Part 2

In the first part ( Validation of React forms. Part 1 ) I described how to work with the react-validate-form , now I will improve the code. Let's take out the input field, hints and errors in a separate block. And connect 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)); 

If your library is not installed, you can download it at git@github.com: tramak / react-validation-boo.git

And if you installed npm install react-validation-boo , then update to the latest version, at the time of publication it is 2.2.4 .
')
Let's now create the components InputBlock , InputCheckboxBlock , InputRadioGroupBlock , TextareaBlock , SelectBlock .

Usually there are several forms display designs. Create a form folder in it; default is our default design and we will create components in it.

 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> ); } } 

We write a block for Select so that options can be passed not only through option tags, but also through an array.

 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> ); } } 

It remains to implement the InputRadioGroupBlock component, we will implement it not on the basis of the existing, but from scratch. The Form component of the react-validation-boo library looks for elements among its descendants with the name field and in them, via props, passes the vBoo object in this object and contains all the necessary methods for working with component validation. First, let's write how we will use the component.

 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> ); } } 

All this is described in the documentation on github, I will add it.

If you find errors or have any suggestions for improvement, write to the mail will be refined, improved.

In the comments to the previous article it was written that there are other good libraries, yes it is, but I think that this is not a reason not to write my own solutions, to refine and improve them when there is a desire to write.

Source: https://habr.com/ru/post/430562/


All Articles