Reactの複雑な形式の検証。 パート1

まず、 react-validation-booコンポーネントをインストールする必要があります。反応に精通しており、その構成方法を知っていると思います。



npm install react-validation-boo



あまり話さないために、すぐに小さなコード例を示します。



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







このコードを解析しましょう。



connect関数から始めましょう。検証ルールとその他の追加パラメーターを渡します。 このメソッドを呼び出すことで、コンポーネント( MyForm )を渡す新しい関数を取得し、 propsでフォーム検証を操作するために必要なメソッドを受け取ります。



コンポーネントのレンダリング関数で、検証ルールconnect = {this.props.connect}に接続するFormコンポーネントを返します。 これは、ネストされたコンポーネントを検証する方法をフォームが知るために必要な構成です。

<Input type = "text" name = "name" />確認する入力フィールド、 ルールプロパティで接続する検証ルールを渡しました。 私たちの場合、この名前は空にしないでください( 必須 )。



コンソールで検証がどのように機能するかを確認するために接続する ロガーも渡しました。



コンポーネントの小道具には、一連の関数があります。



  1. vBoo.isValid() -すべての入力コンポーネントが検証された場合、 trueを返します
  2. vBoo.hasError(name)-nameプロパティを持つコンポーネントが有効でない場合、 trueを返します
  3. vBoo.getError(name)-nameプロパティを持つコンポーネントの場合、エラーテキストを返します


これで徐々に複雑になります。まず、言語を渡して接続し、言語に応じて検証ルールを変更し、さらにフィールドと検証ルールを追加します。



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





この例では、ロシア語のチェックボックス requiredをインストールする必要がありますが、他の場合は常に有効です。



また、関数ラベル(lang)connectに渡し、フィールドの名前を読み取り可能な形式で返します。



コンポーネントの小道具にはlabels関数に渡された値を返すgetLabel(name)関数があります。そのような値がない場合は、 nameを返します。



VBooコアコンポーネント



FormInputInputRadioInputCheckboxSelectTextarea



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





検証ルール



独自の検証ルールを作成する方法を見てみましょう。

ルールを作成するには、 バリデータークラスから継承されるクラスを作成する必要があります。



 import {validator} from 'react-validation-boo'; class myValidator extends validator { /** * name -  ,   label    * value -    * params -     3-    (rules) */ 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;
      
      





次に、バリデーターをフォームに接続します。

 import myValidator from 'path/myValidator'; // ... export default connect({ rules: () => ([ [ 'name', 'required', { error: '%name%    ' } ], [ 'name', 'myValidator', { error: '   params.error' } ] ]), labels: () => ({ name: '' }), validators: { myValidator }, lang: 'ru' })(MyForm);
      
      





毎回すべての検証ルールを登録しないように、それらが登録される別のファイルを作成し、そのバリデーターを接続します: `import 'file-validation`` 。 このフォームに特別なルールがある場合、 バリデーター:Object.assign({}、 `import 'file-validation``、{...})



シナリオ



フォームで実行されるアクションに応じて検証ルールを変更する必要がある場合を考慮してください。



デフォルトでは、この検証を実行するシナリオを指定できるルールにdefaultというスクリプトがあります。



スクリプトが指定されていない場合、すべてのシナリオで検証が実行されます。



 rules = () => ([ [ 'name', 'required', { error: '%name%    ' } ], [ 'name', 'myValidator', { scenario: ['default', 'scenario1'] } ], [ 'email', 'email', { scenario: 'scenario1' } ] ])
      
      





この関数は、コンポーネントのpropsプロパティを介して渡されます。



  1. vBoo.setScenario(シナリオ) -シナリオスクリプトを設定します。一度に複数のスクリプトがアクティブになっている場合、文字列または配列のいずれかです。
  2. vBoo.getScenario() -現在のスクリプトまたはスクリプトの配列を返します
  3. vBoo.hasScenario(名前) -このスクリプトが現在インストールされているかどうか、 名前文字列を示します


フォームにscenariesオブジェクトを追加しましょう。ここには、可能なすべてのスクリプトを保存します。trueはスクリプトがアクティブ、 false はいいえです。



スクリプトを追加および削除する関数addScenariesおよびdeleteScenaries同様に。



「同ha」または「結婚」が選択されている場合、コメントフィールドを追加します 。当然、このフィールドはこの場合、つまりシナリオと結婚したシナリオでのみ検証する必要があります



「詳細」チェックボックスが設定されている場合、必要な追加フィールド、シナリオ「 追加スクリプトを追加します



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





記事を非常に大きくしないために、次の記事に進みます。ここでは、独自のコンポーネント(カレンダーやinputSearchなど)を作成して検証する方法、reduxと関連付ける方法などを記述します。



All Articles