I am trying to create a form in angular that dynamically renders some fields based on an array that is received from the backend.
Let's say that the three possible inputs in the form are ["one", "two", "three", "four"]
.
Then depending on this array, a form should be rendered and the form group should only have inputs mentioned in the received array. In my case let us just say: ["one", "two", "three"]
.
Let's forget the rendering part for now and focus on creating the form group.
As you can see below, the simple code tries to use addControl
method to dynamically add controls to the form group.
When submitting the code, the fields are present as {one: null, two: null, three: null}
.
I have subscribed to the valueChanges
of the form to print out if anything changes.
But when the input of the field one
is changed, there is no event fired and nothing is printed.
Furthermore, when submitted, the object seems to be {one: null, two: null, three: null}
as if nothing changed.
My guess is that somehow, the form template is not being bound to the code in component.ts , but I cannot figure out what is going wrong.
import 'zone.js/dist/zone';
import { Component, OnInit } from '@angular/core';
import { CommonModule } from '@angular/common';
import { bootstrapApplication } from '@angular/platform-browser';
import { FormBuilder, FormControl, FormGroup } from '@angular/forms';
@Component({
selector: 'my-app',
standalone: true,
imports: [CommonModule],
template: `
<h1>Hello from {{name}}!</h1>
<div>
<div class="col-5 form-floating">
<input formControlName="one"/>
<label>One</label>
</div>
</div>
<button (click)="submit()">SUBMIT</button>
`,
})
export class App implements OnInit {
name = 'Angular';
array = ['one', 'two', 'three'];
form!: FormGroup;
constructor(private fb: FormBuilder) {}
ngOnInit() {
this.form = this.fb.group({});
this.createForm();
}
createForm(): void {
this.array.forEach((field: string) => {
this.form.addControl(field, new FormControl(null));
});
this.form.valueChanges.subscribe((x) => {
console.log(x);
});
}
submit(): void {
console.log(this.form.value);
}
}
bootstrapApplication(App);
https://stackblitz.com/edit/angular-5thwux?file=src%2Fmain.ts
You forgot enclosed in a formGroup
<!--I use the *ngIf to avoid initial errors-->
<form *ngIf="form" [formGroup]="form">
<div class="col-5 form-floating">
<input formControlName="one"/>
<label>One</label>
</div>
</div>
</form>
BTW, you can iterate over the array
<form *ngIf="form" [formGroup]="form">
<div *ngFor="let item of array" class="col-5 form-floating">
<input [formControlName]="item"/>
<label>One</label>
</div>
</div>
</form>
Even your array can be an array of object in the way {label:...,field:...}
NOTE: It's strange you have no errors in console in you didn't enclosed in a formGroup