Angular Form Controls im Template mittels Keys Pipe iterieren

Tutorial Angular

von Ardian Shala, 19.05.2018 - update: 20.05.2018
Mithilfe des Angular Reactive FormBuilder lassen sich schnell FormControls definieren und einer FormGroup zuordnen.
Hierbei fügt Angular die FormControls in das jeweilige Objekt unter controls an (z.B.: myFormGroup.controls).
Doch was ist, wenn man den Template Part mittels *ngFor realisierieren möchte und ein eigenes dynamische Formular aufbauen möchte?
Vorraussetzung:
  • Grundkenntnisse Angular - link

Downloads:

Stackblitz Demo

Ausgangslage

Es wird von folgender Struktur ausgegangen:

myForm: FormGroup;

initForm() {
    this.myForm = this.fb.group({
        firstName: this.fb.control(''),
        lastName: this.fb.control(''),
        age: this.fb.control(''),
    });
}

Problem

Nun möchte man die oben erstellten FormControls mittels ngFor im Template iterieren.

<div *ngFor="let control of myForm.controls">
    {{control}}
</div>

Hierbei wird folgender Fehler ausgegeben, da man versucht ein Object zu iterieren und nicht die eigentlichen Keys:
Cannot find a differ supporting object ‚[object Object]‘ of type ‚object‘.

Lösung

Abhilfe schafft hier eine Angular Custom Keys Pipe, welches das Objekt als Parameter erhält und die Object.keys zurückgibt:

import { Pipe, PipeTransform } from '@angular/core';

@Pipe({ name: 'keys', pure: false })
export class KeysPipe implements PipeTransform {
    transform(value: any, args: any[] = null): any {
        return Object.keys(value)
    }
}

Keys Pipe integrieren

Um die custom Angular Keys Pipe im Template verwenden zu können, muss diese in einem Angular Module importiert und deklariert werden:

//hier app.module.ts
//... restliche imports
import { KeysPipe } from './keys.pipe';

@NgModule({
    imports: [
        BrowserAnimationsModule, BrowserModule, ReactiveFormsModule, FormsModule
    ],
    declarations: [AppComponent, KeysPipe],
    bootstrap: [AppComponent]
})
export class AppModule { } 

Keys Pipe im Template anwenden

Die custom Angular Keys Pipe lässt sich nun einfach mittels Pipe-Symbol an das zu iterierende Objekt anfügen:

<div *ngFor="let controlKey of myForm.controls | keys">
    {{controlKey}}
</div>

Die Ausgabe sollte nun wie folgt aussehen:

<div>firstName</div>
<div>lastName</div>
<div>age</div>

Was lässt sich hiermit nun anstellen?

Nun könnte man eine dynamische Component schreiben, welche als Input ein Angular FormControl erwartet.
Das erwartete Control kann man nun über myForm.get() und dem Iterations Element controlKey erhalten.

<div *ngFor="let controlKey of myForm.controls | keys">
    <my-dynamic-component [control]="myForm.get(controlKey)"></my-dynamic-component>
</div>
#angular #form #formcontrol #keys #pipe #reactiveform

Autor: Ardian Shala

Ersteller der Webseite MuchaDev. Selbstständiger IT Constultant für Frontend Technologien.