April 9, 2026
Signal Forms – Schnell reaktive Formulare in Angular
Click here for the english version of this blog post.
Signal Forms in Angular 21: Der schnellste Weg zu reaktiven Formularen
Signal Forms verwenden, wie der Name schon sagt, Angular-Signale anstelle von RxJS Observables, um die gewünschte Reaktivität in Formularen zu erreichen. Die Verwendung von Signalen führt zu vereinfachtem Code und verbesserter Leistung im Vergleich zum älteren Reactive-Forms-Ansatz und bietet gleichzeitig eine einfachere API für die Interaktion als es RxJS Observables tun. Signal Forms befinden sich noch in der Entwicklervorschau, werden aber danach ein hilfreiches Werkzeug sein.
Dieser Artikel behandelt die Grundlagen dieser neu hinzugefügten Angular-Funktion, damit du deren Vorteile in deinen eigenen Anwendungen nutzen kannst!
Aufbau und Syntax von Signal-basierten Formularen
Um ein Signal Form zu erstellen, brauchen wir Folgendes:
- Ein Interface, welches beschreibt, wie unsere Daten aufgebaut sind
- Ein Signal, das diese Daten enthält
- Unser Formular mit diesem Signal initialisieren
- Verweise auf die Felder des Signal Forms in dem Template des Formulars
Im nächsten Abschnitt wird dann erläutert, wie man dem Signal Form eine Validierung hinzufügen kann.
Die Logik: TypeScript-Setup und Signal-Definition
Zunächst definieren wir also einen Datentyp FormData:
|
1 2 3 4 5 |
export interface FormData { name: string; email: string; wantsNewsletter: boolean; } |
Unser Formular fragt den Benutzer nach folgenden Daten:
- Name des Benutzers
- E-Mail-Adresse des Benutzers
- Ob der Benutzer einen Newsletter erhalten möchte
Nun können wir unser formSignal in unserer App-Komponente erstellen und dabei einige Standard-Ausgangsdaten verwenden:
|
1 2 3 4 5 |
formSignal = signal<FormData>({ name: '', email: '', wantsNewsletter: true, }); |
und reichen das Signal weiter an die Funktion form, um unser Formular zu erstellen:
|
1 |
myForm = form(this.formSignal); |
Dieser Aufruf von form erstellt ein FieldTree-Objekt. Dieser FieldTree stellt die Struktur unseres Formulars als Baum dar und ermöglicht es uns, über Punktnotation auf jedes einzelne Formularfeld zuzugreifen, und möglicherweise Validatoren hinzuzufügen sowie Validierungsfehler zu lesen. Weitere Informationen finden Sie in der Angular-API-Dokumentation.
Das Template: Einbindung im HTML-Code
Das ist vorerst der gesamte TypeScript-Code, den wir benötigen. Jetzt müssen wir nur noch das Markup für unser Formular schreiben.
Wir definieren unser Formular mit zwei normalen Eingabefeldern für den Namen und die E-Mail-Adresse sowie einem Kontrollkästchen für das Newsletter-Abonnement. Um diese Eingabefelder mit unserem Signal Form myForm zu verknüpfen, verwenden wir die Direktive formField, um jede Eingabe an das entsprechende Signal im FieldTree zu binden.
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 |
<form> <div> <label> Name: <input [formField]="myForm.name" /> </label> </div> <div> <label> Email: <input [formField]="myForm.email" /> </label> </div> <div> <input type="checkbox" [formField]="myForm.wantsNewsletter" /> Subscribe to Newsletter </div> </form> |
Wir fügen unserem Formular auch einen einfachen Button zum Absenden hinzu,
|
1 |
<button (click)="submit()" type="button">Submit</button> |
welcher die Funktion submit() verwendet, damit wir unser Signal-Formular testen können.
|
1 2 3 |
submit(): void { console.log(this.myForm().value()); } |
Nachdem wir einige Daten eingegeben und in die Konsole geschaut haben, können wir sehen, dass unser Formular die vom Benutzer angegebenen Daten automatisch verfolgt, und wir sind bereit für den nächsten Schritt: die Validierung der Formulareingaben!
Reaktiv und Typ sicher: Validierung mit Signals
Natürlich möchten wir unser Formular auch validieren. Wie können wir das mit Signal Forms tun? Glücklicherweise bieten Signal Forms auch Zugriff auf integrierte Validatoren. Dies macht es sehr einfach, die Formularvalidierung zu definieren: Wir müssen lediglich beim Erstellen eines Formulars festlegen, wie es seine Felder validieren soll, indem wir die bereitgestellten Validatoren verwenden:
|
1 2 3 4 5 |
myForm = form(this.formSignal, (signalRoot) => { required(signalRoot.name, { message: 'Please enter your name' }); required(signalRoot.email, { message: 'Please enter you email' }); email(signalRoot.email, { message: 'Please enter a valid email' }); }); |
Um das Validierungsverhalten festzulegen, übergeben wir zusätzlich eine Funktion an die Funktion form. Diese Funktion erhält das zugrunde liegende Signal des Formulars als Argument, und definiert die Gültigkeitsprüfungen, die wir durchführen möchten:
- Ein Name ist erforderlich
- Eine E-Mail-Adresse ist erforderlich
- Die angegebene E-Mail-Adresse muss gültig sein
Wir geben auch eine hilfreiche Fehlermeldung für jede Validierungsprüfung an. Wir können nun die möglicherweise vom Signal-Formular generierten Fehler verwenden und sie dem Benutzer anzeigen:
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 |
<form> <div> <label> Name: <input [formField]="myForm.name" /> </label> @if (myForm.name().touched() && myForm.name().invalid()) { @for (error of myForm.name().errors(); track error) { <div class="error">{{error.message}}</div> } } </div> <div> <label> Email: <input [formField]="myForm.email" /> </label> @if (myForm.email().touched() && myForm.email().invalid()) { @for (error of myForm.email().errors(); track error) { <div class="error">{{error.message}}</div> } } </div> <div> <input type="checkbox" [formField]="myForm.wantsNewsletter" /> Subscribe to Newsletter </div> <button (click)="submit()" type="button" [disabled]="myForm.invalid()"> Submit </button> </div> |
Und voilà, wir haben gerade unser erstes Signal Form mit Validierung erstellt!
Signal Forms vs. Reactive Forms
Um zu verdeutlichen, warum Signal Forms das Schreiben von Formularen vereinfachen, implementieren wir dasselbe Formular unter Verwendung des Ansatzes der Reactive Forms. Wir erstellen unser Formular mit FormGroup und FormControl und geben dabei die initialen Daten und Validatoren an:
|
1 2 3 4 5 |
myForm = new FormGroup({ name: new FormControl('', Validators.required), email: new FormControl('', [Validators.required, Validators.email]), wantsNewsletter: new FormControl(true), }); |
Und verweisen auf die Formularfelder im Template:
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 |
<form [formGroup]="myForm"> <div> <label> Name: <input formControlName="name" /> </label> @if (myForm.controls.name.touched && myForm.controls.name.invalid) { <div class="error"> @if (myForm.controls.name.hasError('required')) { Please enter your name } </div> } </div> <div> <label> Email: <input formControlName="email" /> </label> @if (myForm.controls.email.touched && myForm.controls.email.invalid) { <div class="error"> @if (myForm.controls.email.hasError('required')) { Please enter your email } @if (myForm.controls.email.hasError('email')) { Please enter a valid email } </div> } </div> <div> <input type="checkbox" formControlName="wantsNewsletter" /> Subscribe to Newsletter </div> <button type="button" (click)="submit()" [disabled]="myForm.invalid"> Submit </button> </form> |
Moment mal… Das scheint genau so einfach zu sein, wie das Erstellen eines Signal Forms? Das stimmt, aber das liegt daran, dass wir dem Formular noch keine eigene Reaktivität hinzugefügt haben.
Warum Signal Forms die bessere Wahl für moderne Apps sind
Stellen wir uns vor, dass das E-Mail-Feld nur dann ausgefüllt werden muss, wenn der Benutzer den Newsletter auch erhalten möchte. Wir können dies zu unserem Reactive Form hinzufügen, indem wir das Feld wantsNewsletter abonnieren und die E-Mail-Validatoren bei einer Änderung im Konstruktor unserer Formularkomponente aktualisieren:
|
1 2 3 4 5 6 7 8 9 10 11 12 13 |
constructor() { this.myForm.controls.wantsNewsletter.valueChanges .pipe(takeUntilDestroyed()) .subscribe((value) => { const emailControl = this.myForm.controls.email; if (value) { emailControl.setValidators([Validators.required, Validators.email]); } else { emailControl.clearValidators(); } emailControl.updateValueAndValidity(); }); } |
An dieser Stelle müssen wir uns mit den zugrunde liegenden RxJS Observables des Reactive Form befassen. Wir müssen sehr vorsichtig sein und dürfen das Observable nur so lange abonnieren, wie es nicht zerstört wird, indem wir takeUntilDestroyed aufrufen und den E-Mail-Validierungsstatus mit updateValueAndValidity aktualisieren, nachdem wir die Validatoren des E-Mail-Feldes geändert haben. Dieser Ansatz ist fehleranfällig und nicht so intuitiv wie der Signal-Forms-Ansatz, bei dem wir die reaktive Gültigkeit zusammen mit unseren anderen Gültigkeitsregeln definieren:
|
1 2 3 4 5 6 7 8 9 10 11 |
myForm = form(this.formSignal, (signalRoot) => { required(signalRoot.name, { message: 'Please enter your name' }); applyWhen( signalRoot.email, ({ valueOf }) => valueOf(signalRoot.wantsNewsletter), (emailPath) => { required(emailPath, { message: 'Please enter your email' }); email(emailPath, { message: 'Please enter a valid email' }); } ); }); |
Wir fügen die erforderlichen E-Mail-Validatoren in einen Aufruf der Funktion applyWhen ein. Diese Funktion nimmt ein Formularfeld als erstes Argument, in unserem Fall das E-Mail-Feld, das nur dann auf Gültigkeit geprüft werden soll, wenn eine bestimmte Bedingung erfüllt ist. Diese Bedingung wird durch das zweite Argument festgelegt, in unserem Fall ({ valueOf }) => valueOf(signalRoot.wantsNewsletter), da wir das E-Mail-Feld nur validieren möchten, wenn das Kontrollkästchen für den Newsletter aktiviert ist. Wir müssen hier die Funktion valueOf verwenden, da die Validierungsfunktion keinen direkten Zugriff auf die Werte der Formularfelder hat. Das dritte Argument von applyWhen legt das Validierungsverhalten wie zuvor fest.
Wenn wir nun das Kontrollkästchen für den Newsletter deaktivieren, müssen wir keine E-Mail-Adresse angeben.
Zusammenfassend lässt sich sagen, dass Signal Forms gegenüber den älteren Reactive Forms viele Vorteile haben. Durch die Verwendung von Signalen sind sie nicht nur schneller, sondern, wie wir im angegebenen Beispiel gesehen haben, auch wirklich einfach zu schreiben und zu verstehen. Der einzige Nachteil von Signal Forms ist, dass sie derzeit noch ein experimentelles Feature sind und sich die API ändern kann. Sie sind also in Produktionsumgebungen mit Vorsicht zu genießen, bis sie stabil sind.
Erfahrung ist der beste Lehrer: Hands-On für Signal Forms
Bist Du bereit, die Theorie in die Praxis umzusetzen? Das Stackblitz enthält nicht nur das Beispiel für die Signal Forms, sondern auch für die Reactive Forms, damit Du direkt alles an einem Ort ausprobieren kannst.
Mit welchen Themen geht es weiter?
Da die Signal Forms einen so großen Einfluss auf das programmieren von reactiven Formularen haben, wollen wir uns auch in den nächsten Artikeln noch mit ihnen beschäftigen. Wir werden uns anschauen, wie man Signal Forms mit Custom Controls verwenden kann und auch genauer auf die Validierung von Signal Forms weiter eingehen. Einen Überblick über alle aktuellen Artikel und Hot Topics von Angular, findest Du auch in unserem Angular Guide.



