I am fairly new to Angular and am trying to build a fairly complex form for a food delivery system I have been building.
I am currently building a form that would enable me to add a menu item to a restaurant's menu.
I have built an Angular form to do this, part of the form includes a section for addons, which would relate to things like sauces, flavors and etc. The data is structured in such a way that there is an addons
array that contains addon objects containing an addon type as well as an array of options relating to that type.
I have built a method to create a new addon in my addons array with two inputs, one for the name being a standard control taking a string and the other being an array nested in this object that includes all the addon options relating to that type.
I am able to add a new addon as well as addon options within that addon object but when trying to update values of those nested options I am unable to attach a formControlName to each of those options which I need in order to update their values.
I keep getting the below error for reference:
vendor.js:63956 ERROR Error: Cannot find control with path: 'addons -> 0 -> 0 -> option
when creating the new option I'm not sure how to give it a unique formcontrol name so that its value can be updated. Any input would be massively appreciated.
Below is my code
Main Form:
menuForm = this.builder.group({
name: this.builder.control<string>('', Validators.required),
price: this.builder.control<string>('', Validators.required),
description: this.builder.control<string>('', Validators.required),
itemType: this.builder.control<string>('', Validators.required),
image: this.builder.control<NonNullable<any>>('', Validators.required),
imageName: this.builder.control<string>('', Validators.required),
categories: this.builder.array([]),
relatedsides: this.builder.array([]),
addons: this.builder.array([]),
});
Methods for adding new addon and adding a new addon option:
addAddon() {
const addOnForm = this.builder.group({
addonname: ['', Validators.required],
addonoptions: this.builder.array([]),
});
this.addons.push(addOnForm);
}
addAddonOption(i: number) {
const addOnOptionForm = this.builder.group({
option: this.builder.control<string>(''),
});
this.addons.value[i].addonoptions.push(addOnOptionForm);
console.log('addons with options', this.addons.value);
}
HTML:
<!-- Addons Array -->
<ng-container type="form" formArrayName="addons">
<h4>Add Addons</h4>
<ng-container *ngFor="let addOnForm of addons.controls; let x = index">
<div [formGroupName]="x" class="addons-form-row">
<mat-form-field appearance="fill">
<input matInput placeholder="Addon" formControlName="addonname" />
</mat-form-field>
<button type="button" (click)="deleteAddOn(x)">Delete Addon</button>
<button type="button" (click)="addAddonOption(x)">
add addon option
</button>
<ng-container
*ngFor="
let addonoption of addons.value[x].addonoptions;
let k = index
"
>
<div [formGroupName]="k" class="imbeded-addon-options">
<mat-form-field appearance="fill">
<input
matInput
type="text"
placeholder="Add On Option"
formControlName="option"
/>
</mat-form-field>
</div>
</ng-container>
</div>
</ng-container>
</ng-container>
<div>
<button type="button" (click)="addAddon()">Add Addon</button>
</div>
Your structure of FormGroup
from the root form to option
control should be:
Root FormGroup
--> addons
FormArray
--> index of addon FormGroup
--> addonoptions
FormArray
--> index of addonoption FormGroup
--> option
FormControl
Miss out formArrayName="addonoptions"
for the template.
Modify the way to iterate the addonoptions
FormArray
from addon
FormGroup
.
<ng-container formArrayName="addonoptions">
<ng-container
*ngFor="
let addonoption of addonoptions(x).controls;
let k = index
"
>
<div [formGroupName]="k" class="imbeded-addon-options">
<mat-form-field appearance="fill">
<input
matInput
type="text"
placeholder="Add On Option"
formControlName="option"
/>
</mat-form-field>
</div>
</ng-container>
</ng-container>
addAddonOption(i: number) {
const addOnOptionForm = this.builder.group({
option: this.builder.control<string>(''),
});
this.addonoptions(i).push(addOnOptionForm);
console.log('addons with options', this.addons.value);
}
addonoptions(addonFormIndex: number): FormArray {
return (this.addons.get(`${addonFormIndex}`) as FormGroup).controls
.addonoptions as FormArray;
}