Validasi bentuk kompleks React. Bagian 1

Pertama, Anda perlu menginstal komponen -validasi-boo reaksi , saya berasumsi bahwa Anda terbiasa dengan reaksi dan tahu cara mengkonfigurasinya.

npm instal validasi validasi-boo

Agar tidak banyak bicara, saya akan segera memberikan contoh kode kecil.

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


Mari kita uraikan kode ini.

Mari kita mulai dengan fungsi koneksi , kami meneruskan aturan validasi kami dan parameter tambahan lainnya. Dengan memanggil metode ini, kami mendapatkan fungsi baru di mana kami melewati komponen kami ( MyForm ) sehingga menerima metode yang diperlukan untuk bekerja dengan validasi formulir dalam alat peraga .

Dalam fungsi render komponen kami, kami mengembalikan komponen Formulir yang kami sambungkan ke aturan validasi connect = {this.props.connect} . Ini adalah desain yang diperlukan untuk Formulir untuk mengetahui cara memvalidasi komponen bersarang.
<Input type = "text" name = "name" /> bidang input yang akan kami periksa, kami melewati aturan verifikasi untuk menghubungkan di properti aturan . Dalam kasus kami, nama ini tidak boleh kosong ( wajib ).

Kami juga melewati middleware: logger untuk menyambungkan untuk melihat bagaimana validasi bekerja di konsol.

Dalam penyangga komponen kami, kami mendapat satu set fungsi:

  1. vBoo.isValid () - mengembalikan true jika semua komponen input telah divalidasi
  2. vBoo.hasError (name) - mengembalikan true jika komponen dengan properti nama tidak valid
  3. vBoo.getError (name) - untuk komponen dengan properti nama , mengembalikan teks kesalahan

Sekarang kita akan secara bertahap menyulitkannya, pertama kita akan melewati bahasa untuk terhubung , sehingga kita dapat mengubah aturan validasi tergantung pada bahasa, dan juga menambahkan bidang tambahan dan aturan validasi.

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

Dalam contoh ini, kotak centang ingat dalam bahasa Rusia harus diinstal diperlukan , tetapi pada kotak lain itu selalu valid.

Kami juga melewati label fungsi (lang) untuk menghubungkan , yang mengembalikan nama bidang dalam bentuk yang dapat dibaca.

Di properti komponen Anda, ada fungsi getLabel (nama) yang mengembalikan nilai yang diteruskan ke fungsi label , atau jika tidak ada nilai seperti itu, ia mengembalikan nama .

Komponen Inti VBoo


Formulir , Input , InputRadio , InputCheckbox , Pilih , 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); 

Aturan validasi


Mari kita lihat cara menulis aturan validasi kita sendiri.
Untuk menulis aturan, Anda harus membuat kelas yang akan diwarisi dari kelas validator .

 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; 

Sekarang hubungkan validator kami ke formulir.
 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); 

Agar tidak mendaftarkan semua aturan validasi Anda setiap kali, buat file terpisah tempat mereka akan didaftarkan dan hubungkan validatornya: `import 'validasi file`` . Dan jika ada aturan khusus untuk formulir ini, maka validator: Object.assign ({}, `import 'validasi file``, {...})

Skenario


Pertimbangkan kasus ketika kita perlu mengubah aturan validasi tergantung pada tindakan yang dilakukan pada formulir.

Secara default, kami memiliki skrip yang disebut default , dalam aturan kami dapat menentukan di bawah skenario mana untuk melakukan validasi ini.

Jika tidak ada skrip yang ditentukan, maka validasi akan dilakukan untuk semua skenario.

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

Fungsi dilewatkan melalui properti alat peraga dari komponen kami:

  1. vBoo.setScenario (scenario) - mengatur skrip skenario, bisa berupa string atau array, jika kita memiliki beberapa skrip aktif sekaligus
  2. vBoo.getScenario () - mengembalikan skrip atau array skrip saat ini
  3. vBoo.hasScenario (name) - apakah skrip ini diinstal sekarang, beri nama string

Mari kita tambahkan objek scenaries dalam bentuk kita, di mana kita akan menyimpan semua skrip yang mungkin, benar skrip aktif, salah tidak.

Serta fungsi addScenaries dan deleteScenaries yang akan menambah dan menghapus skrip.

Jika kita memilih "hidup bersama" atau "menikah", maka kita menambahkan bidang komentar dan tentu saja bidang ini harus divalidasi hanya dalam kasus ini, skenario menikah-skenario .

Jika kami memiliki set "Advanced", maka kami menambahkan bidang tambahan yang akan diperlukan, skrip ' skenario-penambahan '.

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

Agar tidak membuat artikel yang sangat besar, saya akan melanjutkan di yang berikutnya, di mana saya akan menulis cara membuat komponen saya sendiri (misalnya, kalender atau inputSearch) dan memvalidasinya, bagaimana menghubungkannya dengan redux dan banyak lagi.

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


All Articles