I'm trying to build a form. This form has the below structure. My users need to be able to create any amount of entries for the instruction fields.
...
this.buttonForm = this.fb.group({
instructions: this.fb.array([
this.fb.group({
action: this.fb.control('', Validators.required),
data: this.fb.group({
message: this.fb.control(""),
mediaName: this.fb.control(""),
mediaType: this.fb.control(""),
commandName: this.fb.control(""),
commandTrigger: this.fb.control("")
})
})
]),
name: this.fb.control("", Validators.required),
dimensions: this.fb.group({
width: this.fb.control(5, [Validators.required, Validators.min(1)]),
height: this.fb.control(5, [Validators.required, Validators.min(1)]),
positionX: this.fb.control(5, [Validators.required, Validators.min(0)]),
positionY: this.fb.control(5, [Validators.required, Validators.min(0)])
})
});
}
...
get instructionAray() {
return this.buttonForm.get("instructions") as FormArray;
}
public addInstruction() {
this.instructionAray.push(this.fb.control(""));
}
Below is the HTML for the component (excluding the non array items).
<ng-container formArrayName="instructions">
<ng-container *ngFor="let instruction of instructionAray.controls; let i = index" [formGroupName]="i">
<div class="flex flex-col gap-4 border border-solid border-red-300 p-2">
<select #action formControlName="action" class="formBackground"
(change)="resetInstruction(i, $event.target)">
<option value="Command">Command</option>
<option value="Media">Media</option>
<option value="Message">Message</option>
</select>
<div *ngIf="action.value == 'Message'" >
<div class="flex flex-row gap-x-2" formGroupName="data">
<p>Message:</p>
<input type="text" formControlName="message" class="formBackground ml-2">
</div>
</div>
<div *ngIf="action.value == 'Media'" formGroupName="data">
<div class="flex flex-row gap-x-2">
<p>Media:</p>
<input type="text" formControlName="mediaName" class="formBackground ml-2">
</div>
<div class="flex flex-row gap-x-2 mt-2">
<p>Type:</p>
<select formControlName="mediaType" class="formBackground ml-2">
<option value="soundEffect">Sound Effect</option>
<option value="imageGif">Image / GIF / Static</option>
<option value="video">Video</option>
</select>
</div>
</div>
<div *ngIf="action.value == 'Command'" formGroupName='data'>
<div class="flex flex-row mt-2 gap-x-2">
<p>Name:</p>
<input type="text" formControlName="commandName" class="formBackground ml-2">
</div>
<div class="flex flex-row mt-2 gap-x-2">
<p>Trigger:</p>
<select formControlName="commandTrigger" class="formBackground ml-2">
<option selected value="Manual">Manual (Default, only option)</option>
</select>
</div>
</div>
<button (click)="delete(i)" class="bg-red-500 text-white rounded-xl self-center p-2">Delete Instruction</button>
</div>
</ng-container>
</ng-container>
<button (click)="addInstruction()" class="bg-blue-500 text-white rounded-xl self-center p-2 mt-1">
Add Instruction</button>
I'm running into a problem when I try to display the form array data. The first item in the array with the defualt properties displays fine. However, when I add another item to the form array it fails with the below error.
ERROR Error: Cannot find control with path: 'instructions -> 1 -> action'
Angular 11
ButtonFormComponent_ng_container_40_Template button-form.component.html:68
Angular 26
RxJS 6
Angular 23
ButtonFormComponent_Template button-form.component.html:108
Angular 12
BoardComponent_ng_template_3_Template board.component.html:43
Angular 8
openTemplateSheetMenu board.component.ts:52
BoardComponent_div_2_Template__svg_svg_click_1_listener board.component.html:23
Angular 24
BoardComponent_div_2_Template board.component.html:23
Angular 9
BoardComponent_Template board.component.html:20
Angular 2
core.mjs:6412:22
I've been stuck on this for a few days now with no success.