Selamat siang
Hari ini saya ingin berbicara tentang paket baru untuk validasi asinkron dalam proyek yang didasarkan pada
Bereaksi ,
Mobx dan ditulis dalam
naskah .
Pengembangan Frontend Modern melibatkan sejumlah besar logika ketika mengisi halaman dengan dokumen, kuesioner dan dokumen untuk pinjaman, pesanan pembayaran, halaman pendaftaran di situs. Beban logis utama jatuh pada pemeriksaan validasi. Pengembang
sudut memikirkan hal ini dan menawarkan pengembang untuk menggunakan mekanisme
FormControl bawaan untuk tujuan ini, yang, meskipun memiliki sejumlah kelemahan, masih lebih baik daripada tidak adanya solusi seperti pada
React . Situasi ini diperumit oleh fakta bahwa tren perkembangan
React saat ini melibatkan penggunaan mobx untuk mengatur logika bisnis.
Menghadapi masalah ini, kami menyelesaikan semuanya dengan menulis sebuah paket:
@ quantumart / mobx-form-validation-kitKeuntungan paket:
- Seluruhnya di TypeScript
- Kompatibel dengan Mobx (versi 4, yang mendukung, favorit semua orang, IE10)
- Dirancang untuk bekerja dalam React (dapat digunakan dalam proyek tanpa bereaksi)
- Dirancang untuk validasi asinkron
- Mudah ditanamkan dalam proyek yang sudah ada.
Instruksi untuk bekerja dengan paket di bawah potongan.
Pada awalnya kami akan menjelaskan fungsionalitas dari paket
kit @ quantumart / mobx-form-validation , di akhir artikel kami akan menulis halaman yang berfungsi penuh dengan contoh formulir pendaftaran di situs.
Kontrol formulir
@ quantumart / mobx-form-validation-kit memungkinkan Anda membuat lapisan antara sumber data dan formulir untuk ditampilkan. Yang, pada gilirannya, memungkinkan Anda untuk memvalidasinya dan, jika perlu, mengubah data sebelum sampai ke objek asli.
Pustaka @ quantumart / mobx-form-validation-kit berisi tiga kelas utama (komponen validasi) untuk mengelola formulir:
- FormGroup - memungkinkan Anda untuk menggabungkan komponen validasi bersama. Kelas diketik, dan memungkinkan Anda untuk membuat ulang antarmuka dengan daftar bidang sebagai parameter umum. Apa pun terdaftar secara default, sangat disarankan untuk tidak menggunakannya tanpa mengetik, tetapi ada kemungkinan.
- FormControl - digunakan untuk memvalidasi bidang tertentu, kelas yang paling umum digunakan. Kelas diketik, dan mengambil sebagai generik parameter jenis variabel yang harus disimpan. Secara default, string terdaftar, karena defaultnya adalah string, sebagai opsi paling pribadi untuk formulir.
- FormArray - memungkinkan Anda untuk membuat dan mengelola berbagai komponen validasi.
Selain itu, ada kelas abstrak dasar
- AbstractControl - kelas dasar untuk semua kelas validasi yang terdaftar, tidak diketik.
- FormAbstractControl - kelas dasar untuk FormGroup dan FormArray , tidak diketik.
- FormAbstractGroup - bukan kelas dasar yang diketik untuk FormControl, berisi tautan ke elemen html yang sedang dirender.
Praktik terbaik untuk membuat formulir validasi adalah gagasan berikut.
Objek tipe satu
FormGroup dibuat pada formulir dan bidang sudah terdaftar di dalamnya
this.form = new FormGroup<IUserInfo>({ name: new FormControl( this.userInfo.name, [], v => (this.userInfo.name = v) ), surname: new FormControl( this.userInfo.surname, [], v => (this.userInfo.surname = v) )
FormGroup mendukung bersarang, mis.
this.form = new FormGroup<IUserInfo>({ name: new FormControl( this.userInfo.name, [], v => (this.userInfo.name = v) ), surname: new FormControl( this.userInfo.surname, [], v => (this.userInfo.surname = v) ) passport: new FormGroup<IPassport >({ number: new FormControl( this.userInfo.passport.number, [], v => (this.userInfo.passport.number = v) ),
Anda bisa menambahkan
FormArray , yang pada gilirannya bisa dilewati tipe
FormControl dan atau seluruh
FormGroup membuat objek kompleksitas dan struktur apa pun.
- FormArray <FormControl>
FormArray <FormGroup>
FormControl sendiri mengambil set parameter berikut ke dalam konstruktor
- value : TEntity adalah nilai awal yang diketik.
- validator : ValidatorFunctionFormControlHandler [] - satu set validator.
- callbackValidValue : UpdateValidValueHandler | null - fungsi panggil balik yang nilai terakhir terakhir dilewatkan. Itu disebut setiap kali nilai di FormControl berubah dan nilai ini melewati validasi yang dijelaskan.
- aktifkan : (() => boolean) | null - fungsi akan mengaktifkan / menonaktifkan validasi berdasarkan kondisi (selalu diaktifkan secara default). Misalnya, validitas tanggal akhir layanan tidak perlu diperiksa jika kotak centang "Tidak Terbatas" tidak dicentang. Akibatnya, cukup dengan memasukkan fungsi di sini yang memeriksa keadaan bidang yang dapat diamati yang bertanggung jawab atas kotak centang "Tidak Terbatas", Anda dapat secara otomatis mematikan semua validasi yang terkait dengan bidang untuk memeriksa tanggal, daripada mendaftarkan logika ini di masing-masing validasi bidang tanggal.
- additionalData : TAdditionalData | null - blok dengan informasi tambahan memungkinkan Anda untuk menambahkan informasi tambahan ke FormControl tertentu dan menggunakannya nanti, misalnya, untuk visualisasi. Ini nyaman jika ada pembangun untuk FormControl di mana Anda perlu mengurai informasi tertentu, dan tidak meneruskan informasi ini melalui bundel data yang kompleks ke kontrol untuk visualisasi. Meskipun saya tidak dapat memberikan skenario aplikasi yang tepat dan tidak dapat disangkal, lebih baik memiliki kesempatan seperti itu daripada menderita tanpanya.
Ada satu batasan yang dimiliki oleh Angular FormControl : tidak perlu menggunakan kembali objek pada formulir yang berbeda. Yaitu Anda bisa membuat pembuat FormGroup dan membuat objek Anda sendiri di setiap halaman. Tetapi menggunakan satu objek per sekelompok halaman adalah praktik yang buruk.
Selain itu, FormControl diinisialisasi dengan nilai tunggal, dan jika nilai ini diubah, nilai baru tidak akan masuk ke FormControl . Ini dilakukan dengan sengaja, karena, seperti yang telah ditunjukkan oleh praktik, untuk beberapa alasan, semua orang dengan keras kepala berusaha untuk mengedit objek asli dengan melewati validasi, dan bukan nilai di FormControl . Cukup berikan nilai baru ke bidang nilai FormControl untuk memodifikasi objek asli.
FormGroup menerima set parameter berikut di konstruktor:
- kontrol : TControls - objek yang diwarisi dari AbstractControls . Bahkan, cukup buat antarmuka yang diwarisi dari AbstractControls di mana Anda menghitung bidang tipe FormGroup , FormControl , FormArray . Anda tentu saja dapat mengatur tipe ke apa saja , tetapi kemudian semua keuntungan dari TypeScript akan hilang.
- validator : ValidatorFunctionFormGroupHandler [] - satu set validator untuk nilai grup. Misalnya, Anda bisa membuat FormGroup yang berisi dua nilai - tanggal minimum dan maksimum, untuk kontrol pemilihan periode. Di validator inilah Anda harus melewati fungsi / fungsi memeriksa rentang tanggal. Misalnya, tanggal mulai tidak lebih besar dari tanggal akhir
- aktifkan : (() => boolean) | null - fungsi akan mengaktifkan / menonaktifkan validasi berdasarkan kondisi (selalu diaktifkan secara default). Harus dipahami bahwa menerapkan fungsi validasi ke grup menonaktifkan validasi di level seluruh grup. Misalnya, kami memiliki kotak pilihan untuk dokumen identitas. Anda dapat membuat beberapa FormGroup dengan kumpulan bidang dokumen yang berbeda: paspor, SIM, paspor pelaut, dll. ... Dalam fungsi ini, periksa nilai dropdown, dan jika nilai yang dipilih tidak sesuai dengan grup ini, semua pemeriksaan validasi dinonaktifkan. Lebih tepatnya, grup akan dianggap valid, terlepas dari nilai-nilai di dalamnya.
Mari kita bicara tentang bidang FormControl , termasuk keberadaan FormGroup dan FormArray .
Ini adalah bidang yang umum untuk semua kontrol, tetapi setiap kontrol juga memiliki bidang yang unik untuk jenisnya.
Kontrol formulir
- nilai - berisi nilai bidang saat ini. Anda juga dapat menetapkan nilai baru untuk bidang ini.
FormGroup dan FormArray berisi
Validasi
Tentu saja, selain kontrol yang memungkinkan Anda bekerja dengan data, kami membutuhkan validasi sendiri. Paket @ quantumart / mobx-form-validation-kit secara alami berisi sejumlah validasi yang telah ditentukan, dan juga mendukung pembuatan validasi kustom.
Contoh pengaturan validasi untuk FormControl untuk bidang usia.
new FormControl<number>( this.userInfo.age, [required(), minValue(18, " 18 .", ValidationEventTypes.Warning)], v => (this.userInfo.age = v) )
Setiap validasi dengan parameter terbaru membutuhkan:
- Pesan - Pesan validasi.
- eventType - tingkat pesan. 4 tingkat pesan didukung.
- Kesalahan - kesalahan
- Peringatan - peringatan
- Info - Pesan Informasi
- Sukses - pesan tentang validitas. Misalnya, Anda dapat memverifikasi bahwa kata sandi itu sangat kompleks.
Paket berisi set validasi berikut:
- diperlukan (... - bidang wajib diisi
- notEmptyOrSpaces (... - bidang tidak kosong dan tidak hanya berisi spasi. Bahkan, diperlukan, dengan mempertimbangkan larangan ruang.
- pola (regExp: RegExp, ... - parameter pertama adalah ekspresi reguler yang harus cocok dengan bidang. Kesalahan dihasilkan jika tidak ada pencocokan pola.
- invertPattern (regExp: RegExp, ... - parameter pertama adalah ekspresi reguler yang tidak cocok dengan bidang. Kesalahan dihasilkan jika ada kecocokan pola.
- minLength (minlength: number, .... - parameter pertama adalah panjang minimum teks inklusif. Kesalahan dihasilkan jika panjangnya kurang dari yang dikirim.
- maxLength (maxlength: number, .... - parameter pertama adalah panjang maksimum teks inklusif. Kesalahan dikeluarkan jika panjangnya lebih panjang dari yang dikirim.
- absoluteLength (length: number, .... - parameter pertama adalah panjang teks yang tepat. Kesalahan akan terjadi jika panjangnya tidak cocok dengan yang ditentukan.
- minValue (min: TEntity | (() => TEntity), ... - validasi ini hanya ditujukan untuk angka dan tanggal. Kesalahan ditetapkan jika nilainya kurang dari yang ditentukan. Keunikan validasi adalah kemampuan untuk menerima tidak hanya nilai tertentu, tetapi juga fungsi, yang berarti bahwa jika Anda membaca nilai dalam fungsi ini dari bidang @observable objek, validasi itu sendiri akan dimulai kembali tidak hanya ketika bidang di mana validasi digantung diubah, tetapi juga ketika "bidang tertaut" diubah. pertama kecuali bidang tag yang dibaca sebagai nilai @observable.
- maxValue (maks: TEntity | (() => TEntity), ... - validasi ini hanya ditujukan untuk angka dan tanggal. Kesalahan diatur jika nilainya lebih besar dari yang ditentukan. Fitur validasi adalah kemampuan untuk menerima tidak hanya nilai tertentu, tetapi juga fungsi, yang berarti bahwa jika Anda membaca nilai dalam fungsi ini dari bidang @observable objek, validasi itu sendiri akan dimulai kembali tidak hanya ketika bidang di mana validasi digantung diubah, tetapi juga ketika "bidang tertaut" diubah. pertama kecuali bidang tag yang dibaca sebagai nilai @observable
- notContainSpaces (... - tidak seperti notEmptyOrSpaces, kesalahan akan dikeluarkan jika nilainya bahkan mengandung setidaknya satu spasi.
- bandingkan (ekspresi: (nilai: TEntity) => boolean (... - menulis fungsi validasi Anda sendiri menghasilkan banyak kode salin-rekat, pembungkus ini dikembangkan untuk menghilangkan masalah ini. Fungsi validasi ini menerima fungsi sebagai parameter pertama, yang pada gilirannya melewati nilai saat ini) bidang, yang memungkinkan Anda untuk membuat pemeriksaan kompleks, misalnya, menghitung hash untuk TIN atau nomor paspor, dan kemudian mengembalikan true / false. Kesalahan akan ditampilkan jika centang mengembalikan false.
- isEqual (nilai: string ... - cek kecocokan string sederhana.
Berikut ini menjelaskan fungsi pembungkus yang mengontrol aliran pemicu validasi.
Perlu dicatat bahwa set validasi diteruskan ke FormControl , FormGroup , FormArray diluncurkan dalam satu array dan pada kenyataannya tidak memiliki urutan eksekusi. Sebagai hasil dari pekerjaan, kita akan memiliki kesalahan di bidang, peringatan , informasi Pesan , array sukses yang terdiri dari kesalahan, peringatan, digabungkan menjadi satu array, dll ...
Seringkali pelanggan hanya ingin melihat satu kesalahan, dan tidak sekaligus. Selain itu, TOR dapat dirancang sehingga satu pemeriksaan dilakukan hanya setelah yang sebelumnya telah berlalu.
Untuk mengatasi masalah ini, wrapperSequentialCheck digunakan. Panggilan dan aplikasinya tidak berbeda dari validator fungsi biasa, tetapi pada input itu menerima array validator yang akan diluncurkan secara berurutan, mis. Validasi berikutnya hanya dimulai setelah yang sebelumnya berlalu tanpa kesalahan.
Fungsi pembungkus kedua adalah fungsi kontrol aliran validasi. wrapperActivateValidation sebagai parameter pertama menerima fungsi di mana perlu untuk mendaftarkan kondisi untuk aktivasi validasi. Berbeda dengan fungsi aktifkan yang diteruskan ke FormControl, pemeriksaan ini dirancang untuk logika yang lebih kompleks. Misalkan kita memiliki pembangun bersama untuk seluruh bentuk pembayaran FormGroup , dan terlebih lagi, hanya ada satu metode di server yang menerima kumpulan bidang yang sama. Tetapi tangkapannya adalah meskipun bentuknya satu, tergantung pada "jenis pembayaran" kami menunjukkan kumpulan bidang yang berbeda kepada pengguna. Jadi wrapperActivateValidation memungkinkan Anda untuk menulis logika di mana berbagai pemeriksaan akan dilakukan tergantung pada jenis pembayaran.
Penggunaan pembungkus akan terlihat seperti fungsi biasa.
new FormControl( this.userInfo.megapole, [wrapperActivateValidation(() => this.info.A === 10, [ required(), pattern(/\^d{10}$/) ]), wrapperActivateValidation(() => this.info.A === 20, [ wrapperSequentialCheck([ notContainSpaces(), pattern(/\^d{20}$/) ]) ])], v => (this.userInfo.megapole = v) )
Contoh ini menunjukkan bahwa pemeriksaan wajib (), pola (/ \ ^ d {10} $ /) hanya akan dilakukan dengan this.info.A === 10 , dan jika this.info.A === 20 , kemudian notContainSpaces (), validasi pola (/ \ ^ d {20} $ /) akan berfungsi, selain itu, validasi ini akan bekerja secara berurutan, tidak seperti kasus pertama.
Secara alami, saatnya akan tiba ketika set validasi standar tidak lagi cukup.
Maka Anda harus menulis fungsi asinkron Anda sendiri. Untungnya, ini dilakukan tanpa kesulitan khusus.
FormControl awalnya dipertajam oleh fungsi validasi asinkron, yang mungkin ingin pergi ke server untuk data, dan jawaban ini perlu menunggu. Dan sebagai hasilnya, semua validasi tidak sinkron.
async function checkValueOnServer(control: FormControl): Promise<ValidationEvent[]> { if (control.value == null) { return []; } const result = await sendToServer(control.value); if (result.errorMessage) { return [ { message: result.errorMessage, type: ValidationEventTypes.Error, }, ]; } return []; }
Di sini Anda perlu memperhatikan dua objek.
Pertama, kami selalu memikirkan array. Yaitu bahkan, Anda dapat mengembalikan beberapa pesan kesalahan sekaligus, jika diinginkan.
Titik kedua adalah objek yang dikembalikan, ia memiliki set bidang berikut.
- key ?: string - bidang opsional, memungkinkan Anda menentukan "kunci" untuk validasi tertentu. Untuk semua tombol dasar, kunci tersebut unik dan cocok dengan namanya. Anda mungkin ingin menggunakan kunci untuk membuat daftar sebagai reaksi, tetapi seperti yang telah ditunjukkan oleh praktik, ini adalah ide yang buruk. Di masa depan, dalam contoh, saya akan menunjukkan bahwa lebih baik menggunakan pesan, dan tidak menyentuh tombol sama sekali. Bagaimanapun, seperti di Angunar, tetapi kebutuhannya telah berkurang, pada kenyataannya, menjadi 0.
- message : string - pesan validasi. Bidang wajib.
- type : ValidationEventTypes - tipe pesan.
- Kesalahan - kesalahan
- Peringatan - peringatan
- Info - Pesan Informasi
- Sukses - pesan tentang validitas. Misalnya, Anda dapat memverifikasi bahwa kata sandi itu sangat kompleks.
- additionalData ?: ada - informasi tambahan yang dapat dikirim bersama dengan validasi, jika perlu. Ini bisa berupa markup html tambahan atau gaya tertentu. Secara umum, Anda bisa memasukkan semuanya ke dalam apa saja.
Ekstensi
Sihir apa pun didasarkan pada hal-hal sepele. Dan dalam hal ini, agar pengaturan fokus berfungsi, mendapatkan perubahan dari bidang memerlukan penautan FormControl di bidang input tertentu.
Karena FormControl tidak membatasi pengembang dalam jenis data yang divalidasi, karena keserbagunaannya, perlu untuk mengorbankan sedikit penerapan pada elemen reaksi.
Pada saat yang sama, untuk input dan textarea dimungkinkan untuk membuat fungsi sederhana dari pengikatan data ke elemen, untuk komponen lain, prosesor masih harus melakukan upaya minimal untuk mengganti data.
Untuk input, pengikatan elemen ke FormControl (nama) akan terlihat seperti ini.
<input type = "text" {... InputFormControl.bindActions (controls.name)} />
Untuk textarea, mengikat akan seperti ini
<textarea {... TextAreaFormControl.bindActions (controls.name)} />
InputFormControl.bindActions dan TextAreaFormControl.bindActions menerima dua parameter:
- formControl : FormControl - sebenarnya FormControl yang akan digunakan untuk mengikat. Wajib.
- acara ? - Parameter opsional yang berisi daftar fungsi yang dapat dipanggil jika Anda perlu menyesuaikannya. , bindActions - Element, , element FormControl -, . . event. .
, FormControl - .
this.form = new FormGroup<IUserInfo>({ name: new FormControl( this.userInfo.name, [], v => (this.userInfo.name = v) ) });
this.userInfo.name , FormControl . FormControl.for
this.form = new FormGroup<IUserInfo>({ name: FormControl.for(this.userInfo, 'name', []) });
, name name . , TypeScript, name , . userInfo β .
β . :)
Contoh
React TypeScript mobx.
.
npm install @quantumart/mobx-form-validation-kit
,:
,
npm init βy
npm install --save-dev webpack webpack-cli
npm install --save react react-dom
npm install --save-dev @types/react @types/react-dom
npm install --save-dev typescript ts-loader source-map-loadertsconfig.json { "compilerOptions": { "outDir": "./dist/", "sourceMap": true, "noImplicitAny": true, "module": "commonjs", "target": "es6", "jsx": "react", "experimentalDecorators": true, "emitDecoratorMetadata": true } }
- src\components\Hello.tsx
- src\index.tsx
- index.html
- src\assets\global.scss
src\components\
Hello.tsx import * as React from "react"; export class Hello extends React.Component { render() { return ( <h1> Hello from TypeScript and React! </h1> ); } }
src\
index.tsx import * as React from "react"; import * as ReactDOM from "react-dom"; import { Hello } from "./components/Hello"; ReactDOM.render( <Hello />, document.getElementById("example") );
index.html <!DOCTYPE html> <html> <head> <meta charset="UTF-8" /> <title>Hello React!</title> </head> <body> <div id="example"></div> <script src="./node_modules/react/umd/react.development.js"></script> <script src="./node_modules/react-dom/umd/react-dom.development.js"></script> <script src="./dist/main.js"></script> </body> </html> src\assets\global.scss .row { display: inline; }
webpack-dev-server
npm install --save-dev webpack-dev-server
npm install --save-dev awesome-typescript-loader
npm install --save-dev html-webpack-plugin
webpack.config.js const path = require('path'); const HtmlWebpackPlugin = require('html-webpack-plugin'); module.exports = { entry: './src/index.tsx', resolve: { extensions: ['.ts', '.tsx', '.js'] }, output: { path: path.join(__dirname, '/dist'), filename: 'bundle.min.js' }, module: { rules: [ { test: /\.tsx?$/, loader: 'awesome-typescript-loader' }, { test: /\.(scss|css)?$/, use: [ { loader: 'style-loader' }, { loader: 'css-loader', options: { importLoaders: 1, }, }, { loader: 'sass-loader', options: { sourceMap: true } }, ], }, ] }, plugins: [ new HtmlWebpackPlugin({ template: './index.html' }) ] }
, mobx React.
"mobx": "4", "mobx-react": "^6.1.1",
C IE10 mobx, 4 , package.json.
"style-loader": "^0.23.1", "css-loader": "^3.1.0", "node-sass": "^4.12.0", "sass-loader": "^7.1.0"
npm install, .
npm install @quantumart/mobx-form-validation-kit
package.json { "name": "ttt", "version": "1.0.0", "description": "", "main": "index.js", "scripts": { "start": "webpack-dev-server --mode development --open", "test": "echo \"Error: no test specified\" && exit 1" }, "keywords": [], "author": "", "license": "MIT", "devDependencies": { "@types/react": "^16.9.5", "@types/react-dom": "^16.9.1", "awesome-typescript-loader": "^5.2.1", "html-webpack-plugin": "^3.2.0", "source-map-loader": "^0.2.4", "ts-loader": "^6.2.0", "typescript": "^3.6.3", "webpack": "^4.41.0", "webpack-cli": "^3.3.9" }, "dependencies": { "@quantumart/mobx-form-validation-kit": "^1.0.8", "mobx": "4", "mobx-react": "^6.1.1", "react": "^16.10.2", "react-dom": "^16.10.2", "webpack-dev-server": "^3.8.2", "style-loader": "^0.23.1", "css-loader": "^3.1.0", "node-sass": "^4.12.0", "sass-loader": "^7.1.0" } }
npm run startHello from TypeScript and React!
Hello . RegistrationStore RegistrationStore.ts
src\RegistrationStore.ts
import { observable } from "mobx"; export class RegistrationStore { @observable public userInfo = { name: "" }; } export const registrationStore = new RegistrationStore();
Hello.ts, .
import * as React from "react"; import { observer } from "mobx-react"; import { registrationStore } from "../RegistrationStore"; @observer export class Hello extends React.Component { private changeName = (event: React.ChangeEvent<HTMLInputElement>) => { registrationStore.userInfo.name = event.target.value; }; render() { return ( <React.Fragment> <h1>, {registrationStore.userInfo.name}</h1> <div className="row"> <span>:</span> <input type="text" value={registrationStore.userInfo.name} onChange={this.changeName} /> </div> </React.Fragment> ); } }
, Store Mobx. input.
, . , . «» . , .
@quantumart/mobx-form-validation-kit
- .
stc/ErrorWraper.tsx
import * as React from "react"; import { observer } from "mobx-react"; import { FormControl } from "@quantumart/mobx-form-validation-kit"; interface Props { formControl: FormControl; } @observer export class ErrorWraper extends React.Component<Props> { render() { return ( <div> {this.props.children} {this.props.formControl.errors.map(error => ( <span key={error.message} className="error"> {error.message} </span> ))} </div> ); } }
, -, .
Hello.tsx .
- β changeName. {...InputFormControl.bindActions(controls.name)} . .
- β input, input , , , .
- β form store , , , componentWillUnmount registrationStore.form.dispose() . mobx FromControl .
import * as React from "react"; import { observer } from "mobx-react"; import { registrationStore } from "../RegistrationStore"; import { ErrorWraper } from "../ErrorWraper"; import { InputFormControl } from "@quantumart/mobx-form-validation-kit"; @observer export class Hello extends React.Component { constructor(props: any) { super(props); registrationStore.initForm(); } componentWillUnmount() { registrationStore.form.dispose(); } render() { const controls = registrationStore.form.controls; return ( <React.Fragment> <h1>, {registrationStore.userInfo.name}</h1> <div className="row"> <span>:</span> <ErrorWraper formControl={controls.name}> <input type="text" {...InputFormControl.bindActions(controls.name)} /> </ErrorWraper> </div> </React.Fragment> ); } }
RegistrationStore.ts.
.
( ) userInfo, form. - userInfo.
import { observable } from "mobx"; import { FormControl, FormGroup, AbstractControls } from "@quantumart/mobx-form-validation-kit"; interface IUserInfo extends AbstractControls { name: FormControl; } export class RegistrationStore { @observable public userInfo = { name: "" }; @observable public form: FormGroup<IUserInfo>; public initForm(): void { this.form = new FormGroup<IUserInfo>({ name: new FormControl( this.userInfo.name, [], v => (this.userInfo.name = v) ) }); } } export const registrationStore = new RegistrationStore();