Angular 2: patchValue führt bei undefinierten Arrays zu Fehlern

Überblick: Model-Driven Forms

Angular 2 bietet mit dem Konzept der Model-Driven Forms (Reactive Forms) einen Ansatz, der - im Gegensatz zur Nutzung von Template-Driven Forms - bei der Gestaltung von Web-Formularen sehr viele Freiheiten der Gestaltung lässt, die Formularlogik im TypeScript-Code kapselt und sie somit weitestgehend vom HTML-Code entkoppelt.

Das zentrale Konstrukt bei diesem Ansatz ist ein FormGroup-Objekt, welches man entsprechend der Formularstruktur mit weiteren Kontrollelementen, -gruppen oder arrays anreichern kann. Dabei kann man den Aufbau exakt an der Benutzeroberfläche und der benötigten Formular- und Programmlogik ausrichten, ganz unabhängig von der Datenhaltung. Möchte man beispielsweise das Benutzerprofil eines Mitarbeiters im Browser darstellen, so wird im zu verarbeitenden Benutzerdatensatz in der Regel eine Mitarbeiternummer oder ein ähnlicher Schlüsselwert hinterlegt sein, den man für den konkreten Einsatzzweck im Frontend nicht benötigt. Auch kann der Benutzerdatensatz Lücken enthalten, d. h. es fehlen möglicherweise Daten, die im Frontend angezeigt werden könnten.

Werte in das Formular übertragen

Je größer ein solcher Datensatz und das zugehörige Formular werden, desto umständlicher wäre es, die Daten einzeln in die FormGroup zu übertragen. Dafür stellt Angular 2 in der FormGroup-Klasse die Methoden setValue und patchValue zur Verfügung. Für setValue müssen Formular- und Datenstruktur exakt übereinstimmen, was wie oben angesprochen häufig nicht der Fall ist. Haben Formular- und Datenstruktur jedoch nur grundsätzlich den gleichen Aufbau (abgesehen von überflüssigen oder fehlenden Werten), so lassen sich die Daten ganz einfach mit patchValue in das Formular übertragen:

Beispieldaten

profileData = {
		'personID': '123456',
		'name': 'Hans Mustermann',
		'userGroups': ['Mitarbeiter', 'Betriebsrat'],
		'address': {
				'city': 'Berlin'
		}
}

Beispielformular (mit FormBuilder erstellt)

this.profileForm = this.builder.group({
	userData: this.builder.group({
		name: [''],
		userGroups: this.builder.array(['', '']),
		address: this.builder.group({
			street: [''],
			city: ['']
		})
	})
})

Länge des FormArray anpassen, Daten ins Formular übertragen

this.adjustUserGroupsArray();
this.profileForm.patchValue(this.profileData);

Unsere Profildaten enthalten also eine ID, die nicht im Formular verwendet wird, und es fehlt die Angabe eine Straße in der Adresse. Dies macht patchValue jedoch nichts aus.

Gefahrenquellen

Etwas aufpassen muss man lediglich bei der Verwendung von Arrays: Bevor man patchen kann, muss man selbst dafür sorgen, dass im FormArray die gleiche Anzahl an Einträgen zur Verfügung steht, wie man aus dem Datenarray bekommt. Dies passiert im obigen Beispiel in der vorgeschalteten Funktion adjustUserGroupsArray. Der userGroups-Eintrag dürfte sogar (wie der street-Eintrag) in unserem Datensatz fehlen, ohne dass patchValue damit Probleme hätte.

Problematisch wird es jedoch, wenn man ein undefiniertes Array übergibt:

profileData = {
		'personID': '123456',
		'name': undefined,
		'userGroups': undefined,
		'address': undefined
}

Während das FormControl name und das FormControl group beim Patchen mit diesem neuen Datenobjekt keine Probleme haben, wird wegen des undefinierten Arrays der Fehler

ERROR Error: Uncaught (in promise): TypeError: Cannot read property 'forEach' of undefined

ausgegeben, da beim Übertragen der Werte der Arrayname gefunden wird, das Array anschließend jedoch nicht mehr durchlaufen werden kann. Dieser Fehler ist gerade bei großen Datensätzen nicht auf den ersten Blick erkennbar. Daher sollte man immer darauf achten, nicht unnötigerweise undefinierte Einträge zu erzeugen, sondern die Datensätze beim Datentransfer sauber übernehmen.

Nächster Artikel in dieser Reihe:
EntwicklerCamp 2017 - AngularJS und Domino

Sie wollen mehr über assono erfahren?

Zur Startseite

Sie haben Fragen? Wir sind für Sie da.

Wenn Sie mehr über unsere Angebote erfahren möchten, können Sie uns jederzeit kontaktieren. Sie können uns auf verschiedene Weisen für eine unverbindliche Erstberatung erreichen:

assono GmbH

Standort Kiel (Zentrale)
assono GmbH
Lise-Meitner-Straße 1–7
24223 Schwentinental

Standort Hamburg
assono GmbH
Bornkampsweg 58
22761 Hamburg


Telefonnummern:
Zentrale: +49 4307 900 407
Techn. Hotline: +49 4307 900 403
Vertrieb: +49 4307 900 402

E-Mail-Adressen:
kontakt@assono.de
bewerbung@assono.de