It’s #FrontendFriday – Angular Reactive Form über mehrere Komponenten verteilen

09.02.2024

Es ist wieder #FrontendFriday! Vor einiger Zeit standen wir vor der Herausforderung, ein umfangreiches, reaktives und dynamisches Formular zu verwalten, das auf viele UI-Komponenten verteilt werden musste.

Unser Team setzte sich hauptsächlich aus Java-Backend-Entwicklern zusammen, die bisher wenig Erfahrung im Angular-Umfeld gesammelt hatten. So erforderte die Implementierung mehrere Versuche, da zu diesem Zeitpunkt keine guten Best-Practice-Anleitungen verfügbar waren und eine Übersicht über die verschiedenen Möglichkeiten mit ihren Vor- und Nachteilen fehlte. Erst viel später stießen wir auf Artikel von Sandro Roth, die während der Implementierung äußerst hilfreich gewesen wären.

Daher haben wir die wesentlichen Erkenntnisse aus diesen Artikeln hier zusammengefasst und hoffen, dass sie anderen bei der Implementierung eine gute Orientierung bieten werden und mühsame Fehlversuche ersparen können.

 

Überblick

  1. Control Value Accessor
    (für eigene Formularfeld-Komponenten)
  2. Child provides/emits FormGroup to parent
    (saubere Trennung, aber schwierig bei Formular mit übergreifenden Validierungen / Seiteneffekten)
  3. Parent provides FormGroup to child
    (sehr einfach, aber Datenflussprinzip verletzt)
  4. Form Service Approach
    (Kompromiss für Formular mit übergreifenden Validierungen / Seiteneffekten)

(1) Control Value Accessor

Kurzbeschreibung:

  1. Kind-Komponente implementiert ControlValueAccessor (CVA) Interface.
  2. Kind-Formular wird mittels formControlName an Eltern-Formular gebunden.
Vorteile Nachteile
  • Sauberer Ansatz
  • Guter Weg, um eigene Formularfeld-Komponenten zu implementieren, wie z.B. ein Datumsauswahlfeld.

Für Details siehe folgende Artikel:

↑ nach oben

(2) Child provides/emits FormGroup to parent

Kurzbeschreibung:

  1. Kind-Element emittiert sein Formular an die Eltern-Komponente
  2. diese fügt das Kind-Formular mittels addControl zu ihrem Formular hinzu
Vorteile Nachteile
  • relativ einfach
  • gute Testbarkeit
  • keine Namenskonflikte, da sich die Eltern-Komponente um die Benennung der Kind-Formulare kümmert (aber nicht über deren Aufbau)
  • Saubere Trennung von Verantwortlichkeiten, Kontrolle über eigene FormGroup, keine direkte Manipulation des Eltern-Formulars durch die Kind-Komponente
  • Bei Formularen mit vielen Feld-übergreifenden Validierungen und Seiteneffekten (z.B. Zurücksetzen von Feld x, wenn Feld y sich ändert) wird es kompliziert und unschön, manchmal wird dabei der unidirektionale Datenfluss verletzt, was zu Fehlern führen kann. In einem solchen Szenario bietet sich eher der „(4) Form Service Approach“ an.

Für Details siehe folgende Artikel:

↑ nach oben

(3) Parent provides FormGroup to child

Kurzbeschreibung:

  1. Eltern-Komponente übergibt sein Formular an die Kind-Komponente mittels @Input
  2. Kind-Komponente fügt sein Formular zum Eltern-Formular hinzu mittels addControl
Vorteile Nachteile
  • sehr einfach
  • gute Testbarkeit
  • Namenskonflikte möglich: Man muss aufpassen, dass nicht mehrere Kind-Komponenten unter demselben Namen Kind-Formulare zum Eltern-Formular hinzufügen.
  • Datenflussprinzip verletzt (top/parent → bottom/child) und damit potenziell Probleme mit Change Detection

Für Details siehe folgende Artikel:

↑ nach oben

(4) Form Service Approach

Kurzbeschreibung:

  1. Nur der UI-Anteil wird auf viele Einzelkomponenten aufgeteilt. Das Formular selbst wird nicht aufgeteilt, sondern als ein großes Formular in einen Service verlagert, welcher mit Injectable annotiert ist.
  2. In der Formular-Hauptkomponente wird der Service im providers-Array angegeben, wodurch für jede Instanz der Formular-Hauptkomponente auch eine neue Instanz des Services erzeugt wird.
  3. Die Kind-Komponenten injizieren den Formular-Service und greifen auf das Formular zu.
Vorteile Nachteile
  • Feld-übergreifende Validierungen sind viel einfacher zu behandeln
  • Seiteneffekte sind viel einfacher zu behandeln
  • Komponenten einfacher zu verstehen, da das reaktive Formular ausgelagert ist
  • UI-Komponenten sind nicht in sich geschlossen, da das Formular in einem Service verwaltet wird
  • Wiederverwendung der UI-Komponenten in einem anderen Formular schwierig zu implementieren

Für Details siehe folgenden Artikel:

↑ nach oben

 


Handling large reactive forms in Angular (Sandro Roth)

Handling large, typed reactive forms in Angular (Sandro Roth)

Building complex forms with Angular Reactive Forms (Sandro Roth)

Zurück zur Übersicht

Kommentar verfassen

Deine E-Mail-Adresse wird nicht veröffentlicht. Erforderliche Felder sind mit * markiert

*Pflichtfelder

*