What I would like to achieve: To dynamically create a new formGroup for each recipe I receive from the backend (stored in the this.selectedRecipe.ingredients) and then patch the value of each formControl from the newly created formGroup with the data I received.
What I've tried: Until this point, please see below what I have tried so far and at the moment it works partially, but the problem is that it's being created only one instance of formGroup and only patches the value of the last recipe from the this.selectedRecipe.ingredients array and not for each recipe from the array. Finally, what I would like to achieve is to have an instance of formGroup for each recipe in the this.selectedRecipe.ingredients array, and to patch the value of each formControl from formGroup with information from my array.
If you guys have any idea how I can approach this further or what I'm doing wrong I would really appreciate it. Thanks a lot!
HTML
<form [formGroup]="editRecipeF" (ngSubmit)="onSubmitEditRecipeForm()">
<div formGroupName="recipeDetails">
<div class="form-group">
<label for="title">Title</label>
<input
type="text"
id="title"
formControlName="title"
class="form-control"
/>
</div>
<div class="form-group">
<label for="imageUrl">Recipe Image</label>
<input
type="text"
id="imageUrl"
formControlName="imageUrl"
class="form-control"
/>
</div>
</div>
<div formArrayName="ingredients">
<div class="ingredients-div mt-4">
<h2>Ingredients</h2>
<button
class="float-left btn"
mat-icon-button
color="primary"
aria-label="Add"
(click)="onAddIngredients()"
matTooltip="Add"
>
<p>+</p>
</button>
</div>
<div
class="row"
*ngFor="let ingredient of getControls(); let i = index"
[formGroupName]="i"
>
<div class="form-group">
<label for="name">Ingredient Name</label>
<input
class="form-control"
type="text"
name="name"
id="name"
formControlName="name"
/>
</div>
<div class="form-group">
<label for="qty">Ingredient Qty</label>
<input
class="form-control"
type="text"
name="qty"
id="qty"
formControlName="qty"
/>
</div>
</div>
</div>
<button class="btn btn-primary mt-4" type="submit">Submit</button>
</form>
TypeScript
@Component({
selector: "app-edit-recipe",
templateUrl: "./edit-recipe.component.html",
styleUrls: ["./edit-recipe.component.css"],
})
export class EditRecipeComponent implements OnInit {
editRecipeF!: FormGroup;
recipeId: any;
selectedRecipe!: Recipe;
constructor(
private formBuilder: FormBuilder,
private recipesService: RecipesService,
private route: ActivatedRoute
) {}
ngOnInit() {
this.recipeId = this.route.snapshot.params["id"];
this.editRecipeF = this.formBuilder.group({
recipeDetails: this.formBuilder.group({
title: ["", Validators.required],
imageUrl: ["", Validators.required],
duration: ["", Validators.required],
calories: ["", Validators.required],
}),
ingredients: this.formBuilder.array([this.createIngFormGroup()]),
});
this.recipesService.fetchRecipeDetails(this.recipeId).subscribe(
(selectedRecipeDetails) => {
this.selectedRecipe = selectedRecipeDetails;
this.editRecipeF.patchValue({
recipeDetails: {
title: this.selectedRecipe.title,
imageUrl: this.selectedRecipe.imageUrl,
duration: this.selectedRecipe.duration,
calories: this.selectedRecipe.calories,
},
});
const ing = this.editRecipeF.get("ingredients") as FormArray;
for (let ingredient of this.selectedRecipe.ingredients) {
ing.patchValue([
{
name: ingredient.ingName,
qty: ingredient.ingQty,
qtyUnit: ingredient.ingQtyUnit,
imageUrl: ingredient.ingImageUrl,
},
]);
}
},
(error) => {
console.log(error);
}
);
}
private createIngFormGroup() {
return new FormGroup({
name: new FormControl("", Validators.required),
qty: new FormControl("", Validators.required),
qtyUnit: new FormControl("", Validators.required),
imageUrl: new FormControl("", Validators.required),
});
}
public getControls() {
return (<FormArray>this.editRecipeF.get("ingredients")).controls;
}
public onAddIngredients() {
const ingredients = this.editRecipeF.get("ingredients") as FormArray;
ingredients.push(this.createIngFormGroup());
}
public onSubmitEditRecipeForm() {
if (this.editRecipeF.valid) {
console.log(this.editRecipeF.value);
this.recipesService
.editRecipe(this.editRecipeF.value, this.recipeId)
.subscribe(
(success) => {},
(error) => {
console.log(error);
}
);
}
}
}