I am trying to create a dynamic form where you can add forms dynamically, and sub forms dynamically. For example:
+ user1
--- + color1
--- + color2
--- + color3
+ user2
--- + color1
--- + color2
--- + color3
+ user 3
--- + color1
Where as you can add as many users as you want, and you can add as many colors as you want to each user. I can get the first array to work (users), but not sure about the nested array (colors). I have it set up so it loads a user and a color at the beginning. Here is my code I have so far:
export class FormsComponent implements OnInit {
myForm: FormGroup;
constructor(private fb: FormBuilder) { }
ngOnInit() {
this.myForm = this.fb.group({
email: '',
users: this.fb.array([])
})
}
get userForms() {
return this.myForm.get('users') as FormArray
}
get colorForms() {
return this.userForms.get('colors') as FormArray
}
addUser() {
const userGroup = this.fb.group({
user: [],
colors: this.fb.array([])
})
this.userForms.push(userGroup);
}
deleteUser(i) {
this.userForms.removeAt(i);
}
addColor() {
const colorGroup = this.fb.group({
color: []
})
this.colorForms.push(colorGroup);
}
deleteColor(i) {
this.colorForms.removeAt(i)
}
}
And this is my html code:
<form [formGroup]="myForm">
<hr>
<input formControlName="email">
<div formArrayName="users">
<div *ngFor="let user of userForms.controls; let i=index" [formGroupName]="i">
<input formControlName="user">
<button (click)="deleteUser(i)">Delete User</button>
<div formArrayName="colors">
<div *ngFor="let color of colorForms.controls; let t=index" [formGroupName]="t">
<input formControlName="color">
<button (click)="deleteColor(t)">Delete Color</button>
</div>
</div>
</div>
</div>
<button (click)="addUser()">Add User</button>
</form>
Obviously this doesn't work, so I am trying to comprehend what I need to do.
It doesn't work because you do not take into account the index in which controls are stored.
For example
get colorForms() {
return this.userForms.get('colors') as FormArray
}
won't work since userForms
returns FormArray
and you have to specify index to get colors
control which belongs to specific user.
So it might look like:
getColors(index) {
return this.userForms.get([index, 'colors']) as FormArray;
}
and in html:
<div *ngFor="let color of getColors(i).controls;...>
Also you need to keep it in mind when working with colors
array:
addColor(index: number) {
const colorGroup = this.fb.group({
color: []
})
this.getColors(index).push(colorGroup);
^^^^^^^^^^^^
use the them method to get correct FormArray
}
deleteColor(userIndex: number, colorIndex: number) {
this.getColors(userIndex).removeAt(colorIndex);
}
See also Ng-run Example