Guten Tag.
Heute möchte ich über ein neues Paket für asynchrone Validierungen in Projekten sprechen, die auf
React ,
Mobx basieren und in
Typescript geschrieben sind .
Die moderne Frontend-Entwicklung erfordert viel Logik beim Ausfüllen von Seiten mit Dokumenten, Fragebögen und Dokumenten für einen Kredit, Zahlungsaufträgen und Registrierungsseiten auf der Website. Die logische Hauptlast liegt bei den Validierungsprüfungen.
Angular- Entwickler haben über diesen Punkt nachgedacht und bieten Entwicklern an, den integrierten
FormControl- Mechanismus für diese Zwecke zu verwenden, der zwar eine Reihe von Nachteilen aufweist, aber immer noch besser ist als das völlige Fehlen einer solchen Lösung für
React . Die Situation wird durch die Tatsache kompliziert, dass der aktuelle Trend der
React- Entwicklung die Verwendung von Mobx zur Organisation der Geschäftslogik beinhaltet.
Angesichts dieser Probleme haben wir alle gelöst, indem wir ein Paket geschrieben haben:
@ quantumart / mobx-form-validation-kitPaketvorteile:
- Ganz auf TypeScript
- Kompatibel mit Mobx (Version 4, die IE10 unterstützt, jedermanns Favorit)
- Entwickelt für die Arbeit in React (kann in Projekten ohne React verwendet werden)
- Entwickelt für die asynchrone Validierung
- Einfach in ein bestehendes Projekt einzubetten.
Anleitung zum Arbeiten mit der Verpackung unter dem Schnitt.
Zu Beginn werden wir die Funktionalität des
@ quantumart / mobx-Formularvalidierungs-Kit- Pakets beschreiben. Am Ende des Artikels werden wir eine voll funktionsfähige Seite mit einem Beispiel für das Registrierungsformular auf der Website schreiben.
Formcontrol
Mit @ quantumart / mobx-form-validation-kit können Sie eine Ebene zwischen den Quelldaten und dem anzuzeigenden Formular erstellen. Auf diese Weise können Sie sie validieren und gegebenenfalls die Daten ändern, bevor sie zum ursprünglichen Objekt gelangen.

Die
@ quantumart / mobx-Formularvalidierungskit- Bibliothek enthält drei Hauptklassen (Validierungskomponenten) zum Verwalten des Formulars:
- FormGroup - Ermöglicht das Kombinieren von Validierungskomponenten. Die Klasse ist typisiert und ermöglicht es Ihnen, die Schnittstelle mit der Liste der Felder als generischen Parameter neu zu erstellen. Alle sind standardmäßig registriert. Es wird dringend empfohlen, sie nicht ohne Eingabe zu verwenden, es besteht jedoch die Möglichkeit.
- FormControl - wird verwendet, um ein bestimmtes Feld zu validieren, die am häufigsten verwendete Klasse. Die Klasse ist typisiert und verwendet als generischen Parameter den Typ der Variablen, die gespeichert werden soll. Standardmäßig ist string registriert, weil Die Standardeinstellung ist Zeichenfolge als privateste Option für Formulare.
- FormArray - Ermöglicht das Erstellen und Verwalten eines Arrays von Validierungskomponenten.
Darüber hinaus gibt es grundlegende abstrakte Klassen
- AbstractControl - die Basisklasse für alle aufgelisteten Validierungsklassen, nicht typisiert.
- FormAbstractControl - Basisklasse für FormGroup und FormArray , nicht eingegeben.
- FormAbstractGroup - keine typisierte Basisklasse für FormControl, enthält einen Link zum HTML-Element, das gerendert wird.
Die beste Vorgehensweise zum Erstellen eines Validierungsformulars ist die folgende Idee.
Auf dem
Formular wird ein Objekt vom Typ 1
FormGroup erstellt, in dem die Felder bereits aufgeführt sind
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 unterstützt das Verschachteln, d.h.
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) ),
Sie können
FormArray hinzufügen, dem wiederum der Typ
FormControl und / oder die gesamte
FormGroup übergeben werden können , um Objekte beliebiger Komplexität und Struktur zu erstellen.
- FormArray <FormControl>
FormArray <FormGroup>
FormControl selbst übernimmt die folgenden Parameter in den Konstruktor
- value : TEntity ist der eingegebene Anfangswert.
- Validatoren : ValidatorFunctionFormControlHandler [] - eine Reihe von Validatoren.
- callbackValidValue : UpdateValidValueHandler | null - Rückruffunktion, an die der letzte gültige Wert übergeben wird. Es wird jedes Mal aufgerufen, wenn sich ein Wert in FormControl ändert und dieser Wert die beschriebenen Überprüfungen besteht.
- aktivieren : (() => boolean) | null - Die Funktion aktiviert / deaktiviert Validierungen nach Bedingung (immer standardmäßig aktiviert). Beispielsweise muss die Gültigkeit des Enddatums des Dienstes nicht aktiviert werden, wenn das Kontrollkästchen "Unbegrenzt" nicht aktiviert ist. Wenn Sie hier einfach eine Funktion eingeben, die den Status des beobachtbaren Felds aktiviert, das für das Kontrollkästchen "Unbegrenzt" verantwortlich ist, können Sie automatisch alle mit dem Feld verknüpften Überprüfungen zum Überprüfen des Datums deaktivieren und diese Logik nicht in jeder der Datumsfeldüberprüfungen registrieren.
- zusätzliche Daten: TAdditionalData | null - Mit einem Block mit zusätzlichen Informationen können Sie einem bestimmten FormControl zusätzliche Informationen hinzufügen und diese später beispielsweise zur Visualisierung verwenden. Dies ist praktisch, wenn es Builder für FormControl gibt, in denen Sie bestimmte Informationen analysieren müssen und diese Informationen nicht zur Visualisierung über ein komplexes Datenpaket an die Steuerelemente weitergeben müssen. Obwohl ich kein genaues und unbestreitbares Anwendungsszenario angeben kann, ist es besser, eine solche Gelegenheit zu haben, als ohne sie zu leiden.
Angular FormControl hat eine Einschränkung: Es ist nicht erforderlich, Objekte in verschiedenen Formularen wiederzuverwenden. Das heißt, Sie können einen FormGroup- Builder erstellen und auf jeder Seite ein eigenes Objekt erstellen. Die Verwendung eines Objekts pro Seitenbündel ist jedoch eine schlechte Praxis.
Darüber hinaus wird FormControl mit einem einzelnen Wert initialisiert. Wenn dieser Wert geändert wird, wird der neue Wert nicht in FormControl übernommen . Dies geschieht absichtlich, weil, wie die Praxis gezeigt hat, aus irgendeinem Grund jeder hartnäckig versucht, das ursprüngliche Objekt zunächst unter Umgehung von Validierungen zu bearbeiten, und nicht den Wert in FormControl . Weisen Sie dem Wertefeld des FormControl einfach einen neuen Wert zu, um das ursprüngliche Objekt zu ändern.
FormGroup akzeptiert die folgenden Parameter im Konstruktor:
- Steuerelemente : TControls - ein von AbstractControls geerbtes Objekt. Erstellen Sie einfach eine von AbstractControls geerbte Schnittstelle, in der Sie Felder vom Typ FormGroup , FormControl , FormArray auflisten . Sie können den Typ natürlich auf einen beliebigen einstellen, aber dann gehen alle Vorteile von TypeScript verloren.
- Validatoren : ValidatorFunctionFormGroupHandler [] - Eine Reihe von Validatoren für Gruppenwerte. Sie können beispielsweise eine FormGroup erstellen, die zwei Werte enthält - das minimale und das maximale Datum für die Periodenauswahlsteuerung. In diesen Validatoren müssen Sie die Funktion / en zur Überprüfung des Datumsbereichs übergeben. Zum Beispiel, dass das Startdatum nicht größer als das Enddatum ist
- aktivieren : (() => boolean) | null - Die Funktion aktiviert / deaktiviert Validierungen nach Bedingung (immer standardmäßig aktiviert). Es versteht sich, dass das Anwenden der Validierungsfunktion auf eine Gruppe die Validierung auf Gruppenebene deaktiviert. Zum Beispiel haben wir ein Auswahlfeld für ein Ausweisdokument. Sie können mehrere FormGroups mit unterschiedlichen Feldern für Dokumente erstellen: Reisepass, Führerschein, Seemannspass usw. In dieser Funktion überprüfen Sie die Dropdown-Werte. Wenn der ausgewählte Wert nicht dieser Gruppe entspricht, sind alle Validierungsprüfungen deaktiviert. Genauer gesagt wird die Gruppe unabhängig von den darin enthaltenen Werten als gültig betrachtet.
Lassen Sie uns über FormControl- Felder sprechen, einschließlich des Vorhandenseins von FormGroup und FormArray .
Dies waren gemeinsame Felder für alle Steuerelemente, aber jedes Steuerelement verfügt auch über Felder, die für seinen Typ eindeutig sind.
Formcontrol
- value - enthält den aktuellen Wert des Feldes. Sie können diesem Feld auch einen neuen Wert zuweisen.
FormGroup und FormArray enthalten
Validierungen
Zusätzlich zu den Steuerelementen, mit denen Sie mit Daten arbeiten können, benötigen wir natürlich selbst Validierungen. Das Paket @ quantumart / mobx-form-validation-kit enthält natürlich eine Reihe vordefinierter Validierungen und unterstützt auch die Erstellung benutzerdefinierter benutzerdefinierter Validierungen.
Ein Beispiel für das Festlegen von Validierungen für FormControl für ein Altersfeld .
new FormControl<number>( this.userInfo.age, [required(), minValue(18, " 18 .", ValidationEventTypes.Warning)], v => (this.userInfo.age = v) )
Jede Validierung mit den neuesten Parametern dauert:
- Nachricht - Eine Validierungsnachricht.
- eventType - Nachrichtenebene. Es werden 4 Nachrichtenebenen unterstützt.
- Fehler - Fehler
- Warnung - Warnungen
- Info - Informationsmeldungen
- Erfolg - Nachrichten über die Gültigkeit. Sie können beispielsweise überprüfen, ob das Kennwort wirklich komplex ist.
Das Paket enthält die folgenden Validierungen:
- Erforderlich (... - Erforderliches Feld
- notEmptyOrSpaces (... - Das Feld ist nicht leer und enthält nicht nur Leerzeichen. Tatsächlich erforderlich, unter Berücksichtigung des Leerzeichenverbots.
- pattern (regExp: RegExp, ... - Der erste Parameter ist der reguläre Ausdruck, mit dem das Feld übereinstimmen soll. Ein Fehler wird generiert, wenn keine Musterübereinstimmung vorliegt.
- invertPattern (regExp: RegExp, ... - Der erste Parameter ist der reguläre Ausdruck, mit dem das Feld nicht übereinstimmen soll. Bei einer Musterübereinstimmung wird ein Fehler generiert.
- minLength (minlength: number, .... - Der erste Parameter ist die Mindestlänge des Textes einschließlich. Ein Fehler wird generiert, wenn die Länge kleiner als die übertragene ist.
- maxLength (maxlength: number, .... - Der erste Parameter ist die maximale Länge des Textes einschließlich. Ein Fehler wird ausgegeben, wenn die Länge länger als die übertragene ist.
- absoluteLength (Länge: Zahl, .... - Der erste Parameter ist die genaue Länge des Textes. Ein Fehler wird ausgegeben, wenn die Länge nicht mit der angegebenen übereinstimmt.
- minValue (min: TEntity | (() => TEntity), ... - Diese Validierung ist nur für Zahlen und Daten vorgesehen. Ein Fehler wird gesetzt, wenn der Wert kleiner als der angegebene ist. Die Besonderheit der Validierung ist die Fähigkeit, nicht nur einen bestimmten Wert, sondern auch zu akzeptieren Funktion, dh wenn Sie den Wert in dieser Funktion aus dem Feld @observable des Objekts lesen, wird die Validierung selbst nicht nur neu gestartet, wenn das Feld geändert wird, an das die Validierung gehängt wird, sondern auch, wenn das „verknüpfte Feld“ geändert wird. erster Tag-Feld außer dem als Wert @observable gelesen wird.
- maxValue (max: TEntity | (() => TEntity), ... - Diese Validierung ist nur für Zahlen und Daten vorgesehen. Ein Fehler wird gesetzt, wenn der Wert größer als der angegebene ist. Die Validierungsfunktion ist die Fähigkeit, nicht nur einen bestimmten Wert, sondern auch zu akzeptieren Funktion, dh wenn Sie den Wert in dieser Funktion aus dem Feld @observable des Objekts lesen, wird die Validierung selbst nicht nur neu gestartet, wenn das Feld geändert wird, an das die Validierung gehängt wird, sondern auch, wenn das „verknüpfte Feld“ geändert wird. erster außer-Tag-Feld, das als Wert @observable gelesen
- notContainSpaces (... - Im Gegensatz zu notEmptyOrSpaces wird ein Fehler ausgegeben, wenn der Wert sogar mindestens ein Leerzeichen enthält.
- compare (Ausdruck: (Wert: TEntity) => boolean (... - Wenn Sie Ihre eigene Validierungsfunktion schreiben, wird viel Code zum Kopieren und Einfügen generiert. Dieser Wrapper wurde entwickelt, um dieses Problem zu beheben. Diese Validierungsfunktion akzeptiert eine Funktion als ersten Parameter, der wiederum den aktuellen Wert übergibt Felder, mit denen Sie eine komplexe Prüfung durchführen können, z. B. den Hash für die TIN- oder Passnummer berechnen und dann true / false zurückgeben. Ein Fehler wird angezeigt, wenn die Prüfung false zurückgibt.
- isEqual (Wert: Zeichenfolge ... - eine einfache Überprüfung der Zeichenfolgenübereinstimmung.
Im Folgenden werden die Wrapper-Funktionen beschrieben, die den Ablauf der Validierungsauslöser steuern.
Es ist zu beachten, dass der an FormControl , FormGroup , FormArray übergebene Validierungssatz in einem einzelnen Array gestartet wird und tatsächlich keine Ausführungssequenz aufweist. Als Ergebnis der Arbeit werden wir in den Feldern Fehler , Warnungen , Informationsnachrichten , Erfolgsarrays haben, die aus Fehlern, Warnungen bestehen, die zu einem einzigen Array zusammengefasst sind, usw.
Oft möchte der Kunde nur einen Fehler sehen und nicht alle auf einmal. Darüber hinaus kann der TOR so ausgelegt werden, dass eine Prüfung erst durchgeführt wird, nachdem die vorherige bestanden wurde.
Um dieses Problem zu lösen, wird wrapperSequentialCheck verwendet. Sein Aufruf und seine Anwendung unterscheiden sich nicht von dem üblichen Funktionsvalidator, aber am Eingang empfängt er ein Array von Validatoren, die nacheinander gestartet werden, d. H. Die nächste Validierung beginnt erst, nachdem die vorherige fehlerfrei bestanden wurde.
Die zweite Wrapper-Funktion ist die Flusssteuerungsfunktion von Validierungen. wrapperActivateValidation als erster Parameter übernimmt eine Funktion, in die die Bedingungen für die Validierungsaktivierung geschrieben werden sollen. Im Gegensatz zur Aktivierungsfunktion, die an FormControl übergeben wird, ist diese Prüfung für eine komplexere Logik ausgelegt. Angenommen, wir haben einen gemeinsamen Builder für die gesamte FormGroup- Zahlungsform, und außerdem gibt es auf dem Server nur eine Methode, die einen gemeinsamen Satz von Feldern akzeptiert. Der Haken ist jedoch, dass wir dem Benutzer je nach "Zahlungsart" unterschiedliche Felder anzeigen, obwohl es sich um ein Formular handelt. Mit wrapperActivateValidation können Sie also eine Logik schreiben, in der je nach Zahlungsart verschiedene Prüfungen durchgeführt werden.
Die Verwendung von Wrappern sieht genauso aus wie normale Funktionen.
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) )
Dieses Beispiel zeigt, dass die erforderlichen (), Muster- (/ \ ^ d {10} $ /) Prüfungen nur mit this.info.A === 10 und if this.info.A === 20 durchgeführt werden , dann funktionieren notContainSpaces (), Mustervalidierungen (/ \ ^ d {20} $ /) , außerdem funktionieren diese Validierungen im Gegensatz zum ersten Fall nacheinander.
Natürlich wird der Moment kommen, in dem die Standardvalidierungen nicht mehr ausreichen.
Dann müssen Sie Ihre eigenen asynchronen Funktionen schreiben. Glücklicherweise geschieht dies ohne besondere Schwierigkeiten.
FormControl wurde ursprünglich durch asynchrone Validierungsfunktionen geschärft, die möglicherweise Daten an den Server senden möchten, und diese Antwort muss warten. Infolgedessen sind alle Validierungen asynchron.
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 []; }
Hier müssen Sie auf zwei Objekte achten.
Zuerst kümmern wir uns immer um das Array. Das heißt, Auf Wunsch können Sie sogar mehrere Fehlermeldungen gleichzeitig zurückgeben.
Der zweite Punkt ist das zurückgegebene Objekt und enthält die folgenden Felder.
- Schlüssel ?: Zeichenfolge - Ein optionales Feld, mit dem Sie einen "Schlüssel" für eine bestimmte Validierung angeben können. Für alle Basisschlüssel ist der Schlüssel eindeutig und entspricht ihrem Namen. Möglicherweise möchten Sie den Schlüssel verwenden, um die Liste in Reaktion zu rendern, aber wie die Praxis gezeigt hat, ist dies eine schlechte Idee. In Zukunft werde ich im Beispiel zeigen, dass es besser ist, Nachrichten zu verwenden und die Taste überhaupt nicht zu berühren. In jedem Fall ist es wie in Angunar, aber sein Bedarf wurde tatsächlich auf 0 reduziert.
- message : string - eine Validierungsnachricht. Pflichtfeld.
- Typ : ValidationEventTypes - Nachrichtentyp.
- Fehler - Fehler
- Warnung - Warnungen
- Info - Informationsmeldungen
- Erfolg - Nachrichten über die Gültigkeit. Sie können beispielsweise überprüfen, ob das Kennwort wirklich komplex ist.
- AdditionalData ?: any - zusätzliche Informationen, die bei Bedarf zusammen mit der Validierung übertragen werden können. Es kann sich um ein zusätzliches HTML-Markup oder einen bestimmten Stil handeln. Im Allgemeinen können Sie alles in jedes setzen.
Erweiterungen
Jede Magie basiert auf trivialen Dingen. In diesem Fall muss FormControl in einem bestimmten Eingabefeld verknüpft werden, damit die Fokuseinstellung funktioniert und Änderungen aus den Feldern abgerufen werden sollen .
Weil FormControl schränkt den Entwickler nicht auf die Art der validierten Daten ein, da aufgrund seiner Vielseitigkeit ein gewisses Maß an Anwendbarkeit in Reaktionselementen geopfert werden musste.
Gleichzeitig war es für die Eingabe und den Textbereich möglich, einfache Funktionen für die Datenbindung an einem Element zu erstellen. Für andere Komponenten muss der Prozessor nur minimale Anstrengungen unternehmen, um Daten zu ersetzen.
Für die Eingabe sieht die Bindung des Elements an FormControl (Name) folgendermaßen aus.
<input type = "text" {... InputFormControl.bindActions (controls.name)} />
Für den Textbereich ist die Bindung wie folgt
<textarea {... TextAreaFormControl.bindActions (controls.name)} />
InputFormControl.bindActions und TextAreaFormControl.bindActions akzeptieren zwei Parameter:
- formControl : FormControl - eigentlich FormControl, das zum Binden verwendet wird. Erforderlich.
- Ereignisse ? - Ein optionaler Parameter mit einer Liste von Funktionen, die aufgerufen werden können, wenn Sie sie anpassen müssen. , 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 — .
— . :) :)
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();