Einführung in Formulare in Angular 4: Vorlage-getriebene Formulare
German (Deutsch) translation by Valentina (you can also view the original English article)



Formulare sind für jede moderne Front-End-Anwendung von entscheidender Bedeutung und werden täglich verwendet, auch wenn sie nicht erkannt werden. Formulare sind erforderlich, um einen Benutzer sicher bei der App anzumelden, nach allen verfügbaren Hotels in einer bestimmten Stadt zu suchen, ein Taxi zu buchen, eine Aufgabenliste zu erstellen und viele andere Dinge zu tun, die wir gewohnt sind. Einige Formulare enthalten nur einige Eingabefelder, während andere Formulare eine Reihe von Feldern enthalten können, die sich auf mehrere Seiten oder Registerkarten erstrecken.
In diesem Tutorial werden wir über verschiedene Strategien sprechen, die für die Entwicklung von Formularen in Angular verfügbar sind. Unabhängig von der gewählten Strategie sollten in einer Formularbibliothek folgende Punkte behandelt werden:
- Unterstützt die bidirektionale Bindung, damit die Eingabesteuerungswerte mit dem Komponentenstatus synchronisiert sind.
- Behalten Sie den Formularstatus im Auge und verwenden Sie visuelle Hinweise, um den Benutzer darüber zu informieren, ob der aktuelle Status gültig ist oder nicht. Wenn der Benutzername beispielsweise ungültige Zeichen enthält, sollte um das Eingabefeld für den Benutzernamen ein roter Rand angezeigt werden.
- Haben Sie einen Mechanismus, um Validierungsfehler richtig anzuzeigen.
- Aktivieren oder deaktivieren Sie bestimmte Teile des Formulars, sofern einige Validierungskriterien nicht erfüllt sind.
Einführung in Formen in Angular
Angular ist ein vollwertiges Front-End-Framework und verfügt über eigene Bibliotheken zum Erstellen komplexer Formulare. Die neueste Version von Angular verfügt über zwei leistungsstarke Strategien zum Erstellen von Formularen. Sie sind:
- vorlagengesteuerte Formulare
- modellgetriebene oder reaktive Formen
Beide Technologien gehören zur Bibliothek @angle/forms und basieren auf denselben Formularsteuerungsklassen. Sie unterscheiden sich jedoch erheblich in ihrer Philosophie, ihrem Programmierstil und ihrer Technik. Die Auswahl übereinander hängt von Ihrem persönlichen Geschmack und auch von der Komplexität der Form ab, die Sie erstellen möchten. Meiner Meinung nach sollten Sie zuerst beide Ansätze ausprobieren und dann einen auswählen, der zu Ihrem Stil und dem jeweiligen Projekt passt.
Der erste Teil des Tutorials behandelt vorlagengesteuerte Formulare anhand eines praktischen Beispiels: Erstellen eines Anmeldeformulars mit Validierung für alle Formularfelder. Im zweiten Teil dieses Tutorials werden wir die Schritte zum Erstellen desselben Formulars anhand eines modellgetriebenen Ansatzes nachvollziehen.
Vorlage-getriebene Formulare
Der vorlagengesteuerte Ansatz ist eine Strategie, die aus der AngularJS-Ära übernommen wurde. Meiner Meinung nach ist es die einfachste Methode zum Erstellen von Formularen. Wie funktioniert es? Wir werden einige Angular-Direktiven verwenden.
Mit Direktiven können Sie Elementen im DOM Verhalten hinzufügen.- Angular Dokumentation
Angular bietet formularspezifische Anweisungen, mit denen Sie die Formulareingabedaten und das Modell binden können. Die formularspezifischen Anweisungen fügen einem einfachen HTML-Formular zusätzliche Funktionen und Verhaltensweisen hinzu. Das Endergebnis ist, dass die Vorlage Bindungswerte mit der Modell- und Formularvalidierung berücksichtigt.
In diesem Tutorial verwenden wir vorlagengesteuerte Formulare, um die Anmeldeseite einer Anwendung zu erstellen. Das Formular behandelt die gängigsten Formularelemente und verschiedene Validierungsprüfungen für diese Formularelemente. Hier sind die Schritte, die Sie in diesem Tutorial ausführen werden.
- Fügen Sie formsModule zu
app.module.tshinzu. - Erstellen Sie eine Klasse für das Benutzermodell.
- Erstellen Sie die ersten Komponenten und das Layout für das Anmeldeformular.
- Verwenden Sie Angular-Formularanweisungen wie
ngModel,ngModelGroupundngForm. - Fügen Sie die Validierung mit integrierten Validatoren hinzu.
- Validierungsfehler sinnvoll anzeigen.
- Behandeln Sie die Formularübermittlung mit
ngSubmit.
Lassen Sie uns anfangen.
Voraussetzungen
Der Code für dieses Projekt ist auf meinem GitHub-Repo verfügbar. Laden Sie die Zip-Datei herunter oder klonen Sie das Repo, um es in Aktion zu sehen. Wenn Sie lieber von vorne beginnen möchten, stellen Sie sicher, dass Angular CLI installiert ist. Verwenden Sie den Befehl ng, um ein neues Projekt zu generieren.
1 |
$ ng new SignupFormProject |
Generieren Sie als Nächstes eine neue Komponente für die SignupForm.
1 |
ng generate component SignupForm |
Ersetzen Sie den Inhalt von app.component.html durch Folgendes:
1 |
<app-signup-form> </app-signup-form> |
Hier ist die Verzeichnisstruktur für das Verzeichnis src/. Ich habe einige nicht wesentliche Dateien entfernt, um die Dinge einfach zu halten.
1 |
. |
2 |
├── app |
3 |
│ ├── app.component.css |
4 |
│ ├── app.component.html |
5 |
│ ├── app.component.ts |
6 |
│ ├── app.module.ts |
7 |
│ ├── signup-form |
8 |
│ │ ├── signup-form.component.css |
9 |
│ │ ├── signup-form.component.html |
10 |
│ │ └── signup-form.component.ts |
11 |
│ └── User.ts |
12 |
├── index.html |
13 |
├── main.ts |
14 |
├── polyfills.ts |
15 |
├── styles.css |
16 |
├── tsconfig.app.json |
17 |
└── typings.d.ts |
Wie Sie sehen, wurde automatisch ein Verzeichnis für die SignupForm-Komponente erstellt. Dort wird der größte Teil unseres Codes abgelegt. Ich habe auch eine neue User.ts zum Speichern unseres Benutzermodells erstellt.
Die HTML-Vorlage
Bevor wir uns mit der eigentlichen Komponentenvorlage befassen, müssen wir eine abstrakte Vorstellung davon haben, was wir erstellen. Hier ist also die Formstruktur, die ich im Kopf habe. Das Anmeldeformular enthält mehrere Eingabefelder, ein Auswahlelement und ein Kontrollkästchen.



Hier ist die HTML-Vorlage, die wir für unsere Registrierungsseite verwenden werden.
HTML-Vorlage
1 |
<div class="row custom-row"> |
2 |
<div class= "col-sm-5 custom-container jumbotron"> |
3 |
|
4 |
<form class="form-horizontal"> |
5 |
<fieldset>
|
6 |
<legend>SignUp</legend> |
7 |
|
8 |
<!--- Email Block --->
|
9 |
<div class="form-group"> |
10 |
<label for="inputEmail">Email</label> |
11 |
<input type="text" |
12 |
id="inputEmail" |
13 |
placeholder="Email"> |
14 |
</div>
|
15 |
<!--- Password Block --->
|
16 |
<div class="form-group"> |
17 |
<label for="inputPassword">Password</label> |
18 |
<input type="password" |
19 |
id="inputPassword" |
20 |
placeholder="Password"> |
21 |
</div>
|
22 |
|
23 |
<div class="form-group"> |
24 |
<label for="confirmPassword" >Confirm Password</label> |
25 |
<input type="password" |
26 |
id="confirmPassword" |
27 |
placeholder="Password"> |
28 |
</div>
|
29 |
|
30 |
<!--- Select gender Block --->
|
31 |
<div class="form-group"> |
32 |
<label for="select">Gender</label> |
33 |
<select id="select"> |
34 |
<option>Male</option> |
35 |
<option>Female</option> |
36 |
<option>Other</option> |
37 |
</select>
|
38 |
</div>
|
39 |
|
40 |
<!--- Terms and conditions Block --->
|
41 |
<div class="form-group checkbox"> |
42 |
<label>
|
43 |
<input type="checkbox"> Confirm that you've read the Terms and |
44 |
Conditions |
45 |
</label>
|
46 |
</div>
|
47 |
|
48 |
<!--- Buttons Block --->
|
49 |
<div class="form-group"> |
50 |
<button type="reset" class="btn btn-default">Cancel</button> |
51 |
<button type="submit" class="btn btn-primary">Submit</button> |
52 |
</div>
|
53 |
</fieldset>
|
54 |
</form>
|
55 |
</div>
|
56 |
</div>
|
Die in der HTML-Vorlage verwendeten CSS-Klassen sind Teil der Bootstrap-Bibliothek, mit der die Dinge hübsch gemacht werden. Da dies kein Design-Tutorial ist, werde ich nicht viel über die CSS-Aspekte des Formulars sprechen, es sei denn, dies ist erforderlich.
Grundlegende Formulareinrichtung
Um die vorlagengesteuerten Formularanweisungen zu verwenden, müssen Sie das FormsModule aus @angular/forms importieren und dem imports-Array in app.module.ts hinzufügen.
app/app.module.ts
1 |
import { FormsModule } from '@angular/forms'; |
2 |
|
3 |
@NgModule({ |
4 |
.
|
5 |
.
|
6 |
imports: [ |
7 |
BrowserModule, |
8 |
FormsModule
|
9 |
],
|
10 |
.
|
11 |
.
|
12 |
})
|
13 |
export class AppModule { } |
Erstellen Sie als Nächstes eine Klasse, die alle Eigenschaften der Benutzerentität enthält. Wir können entweder eine Schnittstelle verwenden und in der Komponente implementieren oder eine TypeScript-Klasse für das Modell verwenden.
app/User.ts
1 |
export class User { |
2 |
|
3 |
id: number; |
4 |
email: string; |
5 |
//Both the passwords are in a single object
|
6 |
password: { |
7 |
pwd: string; |
8 |
confirmPwd: string; |
9 |
};
|
10 |
gender: string; |
11 |
terms: boolean; |
12 |
|
13 |
constructor(values: Object = {}) { |
14 |
//Constructor initialization
|
15 |
Object.assign(this, values); |
16 |
}
|
17 |
|
18 |
}
|
Erstellen Sie jetzt eine Instanz der Klasse in der SignupForm-Komponente. Ich habe auch eine zusätzliche Eigenschaft für das Geschlecht deklariert.
app/signup-form/signup-form.component.ts
1 |
import { Component, OnInit } from '@angular/core'; |
2 |
// Import the User model
|
3 |
import { User } from './../User'; |
4 |
|
5 |
@Component({ |
6 |
selector: 'app-signup-form', |
7 |
templateUrl: './signup-form.component.html', |
8 |
styleUrls: ['./signup-form.component.css'] |
9 |
})
|
10 |
export class SignupFormComponent implements OnInit { |
11 |
|
12 |
//Property for the gender
|
13 |
private gender: string[]; |
14 |
//Property for the user
|
15 |
private user:User; |
16 |
|
17 |
ngOnInit() { |
18 |
|
19 |
this.gender = ['Male', 'Female', 'Others']; |
20 |
//Create a new user object
|
21 |
this.user = new User({ |
22 |
email:"", password: { pwd: "" , confirm_pwd: ""}, |
23 |
gender: this.gender[0], terms: false}); |
24 |
}
|
25 |
|
26 |
}
|
Für die Datei signup-form.component.html verwende ich dieselbe HTML-Vorlage wie oben beschrieben, jedoch mit geringfügigen Änderungen. Das Anmeldeformular enthält ein Auswahlfeld mit einer Liste von Optionen. Obwohl dies funktioniert, werden wir es auf Angular-Weise tun, indem wir die Liste mit der ngFor-Direktive durchlaufen.
app/signup-form/signup-form.component.html
1 |
<div class="row custom-row"> |
2 |
<div class= "col-sm-5 custom-container jumbotron"> |
3 |
|
4 |
<form class="form-horizontal"> |
5 |
<fieldset>
|
6 |
<legend>SignUp</legend> |
7 |
. |
8 |
. |
9 |
<!--- Gender Block -->
|
10 |
<div class="form-group"> |
11 |
<label for="select">Gender</label> |
12 |
<select id="select"> |
13 |
|
14 |
<option *ngFor = "let g of gender" |
15 |
[value] = "g"> {{g}} |
16 |
</option>
|
17 |
</select>
|
18 |
</div>
|
19 |
. |
20 |
. |
21 |
</fieldset>
|
22 |
</form>
|
23 |
</div>
|
24 |
</div>
|
Als Nächstes möchten wir die Formulardaten an das Benutzerklassenobjekt binden, sodass beim Eingeben der Anmeldedaten in das Formular ein neues Benutzerobjekt erstellt wird, in dem diese Daten vorübergehend gespeichert werden. Auf diese Weise können Sie die Ansicht mit dem Modell synchron halten. Dies wird als Bindung bezeichnet.
Es gibt verschiedene Möglichkeiten, dies zu erreichen. Lassen Sie mich zunächst ngModel und ngForm vorstellen.
ngForm und ngModel
ngForm und ngModel sind Angular-Direktiven, die für die Erstellung vorlagengesteuerter Formulare unerlässlich sind. Beginnen wir zuerst mit ngForm. Hier ist ein Auszug über ngForm aus den Angular-Dokumenten.
DieNgForm-Direktive ergänzt dasform-Element um zusätzliche Funktionen. Es enthält die Steuerelemente, die Sie für die Elemente mit einerngModel-Direktive und einemname-Attribut erstellt haben, und überwacht deren Eigenschaften, einschließlich ihrer Gültigkeit. Es hat auch eine eigenevalid-Eigenschaft, die nur dann wahr ist, wenn jedes enthaltene Steuerelement gültig ist.
Aktualisieren Sie zunächst das Formular mit der Anweisung ngForm:
app/signup-form/signup-form.component.html
1 |
<form
|
2 |
class="form-horizontal" |
3 |
#signupForm = "ngForm"> |
4 |
. |
5 |
. |
6 |
</form>
|
#signupForm ist eine Vorlagenreferenzvariable, die auf die ngForm-Direktive verweist, die das gesamte Formular steuert. Das folgende Beispiel zeigt die Verwendung eines ngForm-Referenzobjekts zur Validierung.
app/signup-form/signup-form.component.html
1 |
<button
|
2 |
type="submit" |
3 |
class="btn btn-success" |
4 |
[disabled]="!signupForm.form.valid"> |
5 |
Submit |
6 |
</button>
|
Hier gibt signupForm.form.valid false zurück, es sei denn, alle Formularelemente bestehen ihre jeweiligen Validierungsprüfungen. Die Schaltfläche "Senden" wird deaktiviert, bis das Formular gültig ist.
Für das Binden der Vorlage und des Modells gibt es viele Möglichkeiten, dies zu tun, und ngModel verfügt über drei verschiedene Syntaxen, um diese Situation zu lösen. Sie sind:
- [(ngModel)]
- [ngModel]
- ngModel
Beginnen wir mit dem ersten.
Zweiwege-Bindung mit [(ngModel)]
[(ngModel)] führt eine bidirektionale Bindung zum Lesen und Schreiben von Eingabesteuerungswerten durch. Wenn eine [(ngModel)]-Direktive verwendet wird, nimmt das Eingabefeld einen Anfangswert aus der gebundenen Komponentenklasse und aktualisiert ihn zurück, wenn eine Änderung des Eingabesteuerungswerts erkannt wird (bei Tastendruck und Tastendruck). Das Bild unten beschreibt den bidirektionalen Bindungsprozess besser.



Hier ist der Code für das E-Mail-Eingabefeld:
1 |
<div class="form-group"> |
2 |
<label for="inputEmail">Email</label> |
3 |
<input type="text" |
4 |
[(ngModel)] = "user.email" |
5 |
id="inputEmail" |
6 |
name="email" |
7 |
placeholder="Email"> |
8 |
</div> |
[(ngModel)] = "user.email" bindet die E-Mail-Eigenschaft des Benutzers an den Eingabewert. Ich habe auch ein name-Attribut hinzugefügt und name ="email" gesetzt. Dies ist wichtig und Sie erhalten eine Fehlermeldung, wenn Sie bei der Verwendung von ngModel kein Namensattribut deklariert haben.
Fügen Sie in ähnlicher Weise jedem Formularelement ein [(ngModel)] und ein eindeutiges name-Attribut hinzu. Ihr Formular sollte jetzt ungefähr so aussehen:
app/signup-form/signup-form.component.html
1 |
. |
2 |
. |
3 |
. |
4 |
<div ngModelGroup="password"> |
5 |
<div class="form-group" > |
6 |
<label for="inputPassword">Password</label> |
7 |
<input type="password" |
8 |
[(ngModel)] = "user.password.pwd" name="pwd" |
9 |
placeholder="Password"> |
10 |
</div>
|
11 |
|
12 |
<div class="form-group"> |
13 |
<label for="confirmPassword" >Confirm Password</label> |
14 |
<input type="password" |
15 |
[(ngModel)] = "user.password.confirmPwd" name="confirmPwd" |
16 |
placeholder="Confirm Password"> |
17 |
</div>
|
18 |
</div>
|
19 |
<div class="form-group"> |
20 |
<label for="select">Gender</label> |
21 |
<select id="select" |
22 |
[(ngModel)] = "user.gender" name = "gender"> |
23 |
|
24 |
<option *ngFor = "let g of gender" |
25 |
[value] = "g"> {{g}} |
26 |
</option>
|
27 |
</select>
|
28 |
</div>
|
29 |
|
30 |
. |
31 |
. |
32 |
. |
Die ngModelGroup wird verwendet, um ähnliche Formularfelder zu gruppieren, sodass Validierungen nur für diese Formularfelder ausgeführt werden können. Da beide Kennwortfelder miteinander verbunden sind, werden sie unter einer einzigen ngModelGroup zusammengefasst. Wenn alles wie erwartet funktioniert, sollte die komponentengebundene user-Eigenschaft für das Speichern aller Formularsteuerungswerte verantwortlich sein. Fügen Sie nach dem Formular-Tag Folgendes hinzu, um dies in Aktion zu sehen:
1 |
{{user | json}} |
Führen Sie die Benutzereigenschaft durch die JsonPipe, um das Modell im Browser als JSON zu rendern. Dies ist hilfreich beim Debuggen und Protokollieren. Sie sollten eine JSON-Ausgabe wie diese sehen.



Die Werte fließen von der Ansicht in das Modell ein. Was ist umgekehrt? Versuchen Sie, das Benutzerobjekt mit einigen Werten zu initialisieren.
app/signup-form/signup-form.component.ts
1 |
this.user = new User({ |
2 |
//initialized with some data
|
3 |
email:"thisisfromthemodel@example.com", |
4 |
password: { pwd: "" , confirm_pwd: ""}, |
5 |
gender: this.gender[0] |
6 |
|
7 |
});
|
Und sie erscheinen automatisch in der Ansicht:
1 |
{ "email": "thisisfromthemodel@example.com", |
2 |
"password": { "pwd": "", "confirm_pwd": "" }, |
3 |
"gender": "Male" |
4 |
}
|
Mit der Zwei-Wege-Bindungssyntax [(ngModel)] können Sie mühelos Formulare erstellen. Es hat jedoch bestimmte Nachteile; Daher gibt es einen alternativen Ansatz, der ngModel oder [ngModel] verwendet.
Hinzufügen von ngModel zum Mix
Wenn ngModel verwendet wird, sind wir tatsächlich dafür verantwortlich, die Komponenteneigenschaft mit den Eingabesteuerungswerten zu aktualisieren und umgekehrt. Die Eingabedaten fließen nicht automatisch in die Benutzereigenschaft der Komponente.
Ersetzen Sie also alle Instanzen von [(ngModel)] = "" durch ngModel. Wir behalten das name-Attribut bei, da alle drei Versionen von ngModel das name-Attribut benötigen, um zu funktionieren.
app/signup-form/signup-form.component.html
1 |
<div class="form-group"> |
2 |
<label for="inputEmail">Email</label> |
3 |
<input type="text" |
4 |
ngModel
|
5 |
id="inputEmail" |
6 |
name="email" |
7 |
placeholder="Email"> |
8 |
</div> |
Mit ngModel wird der Wert des Namensattributs zu einem Schlüssel des zuvor erstellten ngForm-Referenzobjekts signupForm. So speichert signupForm.value.email beispielsweise den Steuerwert für die E-Mail-ID.
Ersetzen Sie {{user | json}} mit {{signupForm.value | json}}, da dort gerade der gesamte Status gespeichert ist.
Einwegbindung mit [ngModel]
Was ist, wenn Sie den Anfangszustand über die gebundene Klassenkomponente festlegen müssen? Das macht das [ngModel] für Sie.



Hier fließen die Daten vom Modell in die Ansicht. Nehmen Sie die folgenden Änderungen an der Syntax vor, um die Einwegbindung zu verwenden:
app/signup-form/signup-form.component.html
1 |
<div class="form-group"> |
2 |
<label for="inputEmail">Email</label> |
3 |
<input type="text" |
4 |
[ngModel] = "user.email" |
5 |
id="inputEmail" |
6 |
name="email" |
7 |
placeholder="Email"> |
8 |
</div>
|
Welchen Ansatz sollten Sie wählen? Wenn Sie [(ngModel)] und ngForm zusammen verwenden, müssen Sie möglicherweise zwei Zustände verwalten - user und signupForm.value - und das kann möglicherweise verwirrend sein.
1 |
{ "email": "thisisfromthemodel@example.com", |
2 |
"password": { "pwd": "thisispassword", "confirm_pwd": "thisispassword" }, |
3 |
"gender": "Male" |
4 |
} //user.value |
5 |
|
6 |
{ "email": "thisisfromthemodel@example.com", |
7 |
"password": { "pwd": "thisispassword", "confirm_pwd": "thisispassword" }, |
8 |
"gender": "Male" |
9 |
} //signupForm.value |
Daher werde ich empfehlen, stattdessen die Einwegbindungsmethode zu verwenden. Aber das müssen Sie selbst entscheiden.
Validierung und Anzeige von Fehlermeldungen
Hier sind unsere Anforderungen für die Validierung.
- Alle Formularsteuerelemente sind erforderlich.
- Deaktivieren Sie die Schaltfläche "Senden", bis alle Eingabefelder ausgefüllt sind.
- Das E-Mail-Feld sollte ausschließlich eine E-Mail-ID enthalten.
- Das Passwortfeld sollte eine Mindestlänge von 8 haben.
- Sowohl das Passwort als auch die Bestätigung sollten übereinstimmen.



Der erste ist einfach. Sie müssen jedem Formularelement wie folgt ein required-Validierungsattribut hinzufügen:
app/signup-form/signup-form.component.html
1 |
<input type="text" |
2 |
[ngModel] = "user.email" name="email" |
3 |
#email = "ngModel" |
4 |
placeholder="Email" |
5 |
required> |
Neben dem required Attribut habe ich auch eine neue Referenzvariable für #email-Vorlagen exportiert. Auf diese Weise können Sie über die Vorlage selbst auf das Winkelsteuerelement des Eingabefelds zugreifen. Wir werden es verwenden, um Fehler und Warnungen anzuzeigen. Verwenden Sie nun die deaktivierte Eigenschaft der Schaltfläche, um die Schaltfläche zu deaktivieren:
app/signup-form/signup-form.component.html
1 |
<button
|
2 |
type="submit" |
3 |
class="btn btn-success" |
4 |
[disabled]="!signupForm.form.valid"> |
5 |
Submit |
6 |
</button>
|
Verwenden Sie zum Hinzufügen einer Einschränkung für E-Mails das Musterattribut, das mit Eingabefeldern funktioniert. Muster werden verwendet, um reguläre Ausdrücke wie den folgenden anzugeben:
1 |
pattern="[a-z0-9._%+-]+@[a-z0-9.-]+\.[a-z]{2,3}$"
|
Für das Kennwortfeld müssen Sie lediglich ein Attribut minlength="" hinzufügen:
app/signup-form/signup-form.component.html
1 |
<input type="password" |
2 |
ngModel
|
3 |
id="inputPassword" |
4 |
name="pwd" |
5 |
#pwd = "ngModel" |
6 |
placeholder="Password" |
7 |
minlength="8" |
8 |
required> |
Um die Fehler anzuzeigen, verwende ich die bedingte Direktive ngIf für ein div-Element. Beginnen wir mit dem Eingabesteuerungsfeld für E-Mail:
app/signup-form/signup-form.component.html
1 |
<div class="form-group"> |
2 |
<label for="inputEmail">Email</label> |
3 |
<input type="text" |
4 |
[ngModel] = "user.email" name="email" |
5 |
#email = "ngModel" id="inputEmail" |
6 |
placeholder="Email" |
7 |
pattern="[a-z0-9._%+-]+@[a-z0-9.-]+\.[a-z]{2,3}$" |
8 |
required> |
9 |
</div>
|
10 |
|
11 |
<!-- This is the error section -->
|
12 |
|
13 |
<div *ngIf="email.invalid && (email.dirty || email.touched)" |
14 |
class="alert alert-danger"> |
15 |
<div *ngIf = "email.errors?.required"> |
16 |
Email field can't be blank |
17 |
</div>
|
18 |
<div *ngIf = "email.errors?.pattern && email.touched"> |
19 |
The email id doesn't seem right |
20 |
</div>
|
21 |
</div>
|
Hier ist viel los. Beginnen wir mit der ersten Zeile des Fehlerabschnitts.
1 |
<div *ngIf="email.invalid && (email.dirty || email.touched)" |
2 |
class="alert alert-danger"> |
Erinnern Sie sich an die Variable #email, die wir zuvor exportiert haben? Es enthält einige Informationen zum Eingabesteuerungsstatus des E-Mail-Felds. Dies umfasst: email.valid, email.invalid, email.dirty, email.pristine, email.touched, email.untouched und email.errors. Das folgende Bild beschreibt jede dieser Eigenschaften im Detail.



Das div-Element mit dem *ngIf wird also nur gerendert, wenn die E-Mail ungültig ist. Der Benutzer wird jedoch mit Fehlern begrüßt, dass die Eingabefelder leer sind, noch bevor er die Möglichkeit hat, das Formular zu bearbeiten.
Um dieses Szenario zu vermeiden, haben wir die zweite Bedingung hinzugefügt. Der Fehler wird erst angezeigt, nachdem das Steuerelement besucht oder der Wert des Steuerelements geändert wurde.
Die verschachtelten div-Elemente werden verwendet, um alle Fälle von Validierungsfehlern abzudecken. Wir verwenden email.errors, um alle möglichen Validierungsfehler zu überprüfen und sie dem Benutzer dann in Form von benutzerdefinierten Nachrichten wieder anzuzeigen. Befolgen Sie nun das gleiche Verfahren für die anderen Formularelemente. Hier ist, wie ich die Validierung für die Passwörter codiert habe.
app/signup-form/signup-form.component.html
1 |
<div ngModelGroup="password" #userPassword="ngModelGroup" required > |
2 |
<div class="form-group"> |
3 |
<label for="inputPassword">Password</label> |
4 |
<input type="password" |
5 |
ngModel name="pwd" |
6 |
id="inputPassword" placeholder="Password" |
7 |
minlength ="8" required> |
8 |
</div>
|
9 |
|
10 |
<div class="form-group"> |
11 |
<label for="confirmPassword" >Confirm Password</label> |
12 |
<input type="password" |
13 |
ngModel name="confirmPwd" |
14 |
id="confirmPassword" placeholder="Confirm Password"> |
15 |
</div>
|
16 |
|
17 |
|
18 |
<div *ngIf="(userPassword.invalid|| userPassword.value?.pwd != userPassword.value?.confirmPwd) && (userPassword.touched)" |
19 |
class="alert alert-danger"> |
20 |
|
21 |
<div *ngIf = "userPassword.invalid; else nomatch"> |
22 |
Password needs to be more than 8 characters |
23 |
</div>
|
24 |
<ng-template #nomatch > |
25 |
Passwords don't match |
26 |
</ng-template>
|
27 |
</div>
|
28 |
</div>
|
Das fängt an, ein bisschen chaotisch auszusehen. Angular verfügt über eine begrenzte Anzahl von Validatorattributen: required, minlength, maxlength und pattern. Um ein anderes Szenario wie das des Kennwortvergleichs abzudecken, müssen Sie sich wie oben beschrieben auf verschachtelte ngIf-Bedingungen verlassen. Oder erstellen Sie im Idealfall eine benutzerdefinierte Validierungsfunktion, die ich im dritten Teil dieser Serie behandeln werde.
Im obigen Code habe ich die ngIf else-Syntax verwendet, die in der neuesten Version von Angular eingeführt wurde. So funktioniert es:
1 |
<div *ngIf="isValid;else notvalid"> |
2 |
Valid content... |
3 |
</div>
|
4 |
|
5 |
<ng-template #notValid>Not valid content...</ng-template> |
Senden Sie das Formular mit ngSubmit
Wir haben das Formular fast fertiggestellt. Jetzt müssen wir in der Lage sein, das Formular zu senden, und die Steuerung der Formulardaten sollte an eine Komponentenmethode übergeben werden, z. B. onFormSubmit().
app/signup-form/signup-form.component.ts
1 |
<form novalidate |
2 |
(ngSubmit)="onFormSubmit(signupForm)" |
3 |
#signupForm="ngForm"> |
4 |
... |
Nun zur Komponente:
app/signup-form/signup-form.component.ts
1 |
...
|
2 |
public onFormSubmit({ value, valid}: { value: User, valid: boolean }) { |
3 |
this.user = value; |
4 |
console.log( this.user); |
5 |
console.log("valid: " + valid); |
6 |
}
|
7 |
...
|
Letzte Demo
Hier ist die endgültige Version der Anwendung. Ich habe ein paar Bootstrap-Klassen hinzugefügt, um das Formular hübsch zu machen.
Zusammenfassung
Wir sind alle hier fertig. In diesem Tutorial haben wir alles behandelt, was Sie zum Erstellen eines Formulars in Angular mithilfe des vorlagengesteuerten Ansatzes wissen müssen. Vorlagengesteuerte Formulare sind wegen ihrer Einfachheit und Benutzerfreundlichkeit beliebt.
Wenn Sie jedoch ein Formular mit vielen Formularelementen erstellen müssen, wird dieser Ansatz unübersichtlich. Im nächsten Tutorial werden wir uns also mit der modellgetriebenen Methode zum Erstellen derselben Form befassen.
Teilen Sie Ihre Gedanken in den Kommentaren unten.



