angulartypescriptangular-reactive-formsformarrayangular-validation

Angular - Get errors in reactive form with loop for the FormArray


I'm using Angular CLI version 16.2.1.

I'm following a course and I'm using reactive forms: In a 'Recipe' list I need to add a Recipe with some inputs and a list of ingredients. The problem is that everytime I try to add an ingredient (with a *ngFor of controls), I get errors.

HTML

<div class="row">
    <div class="col-xs-12" formArrayName="ingredients">
        <div class="row" *ngFor="let ingredientCtrl of getControls(); let i = index" [formGroupName]="i" style="margin-top: 10px;">
            <div class="col-xs-8">
                <input type="text" class="form-control" formControlName="name">
            </div>
            <div class="col-xs-2">
                <input type="number" class="form-control" formControlName="amount">
            </div>
            <div class="col-xs-2">
                <button class="btn btn-danger">X</button>
            </div>
        </div>
        <hr>
        <div class="row">
            <div class="col-xs-12">
                <button type="button" class="btn btn-success" (click)="onAddIngredient()">Add Ingredient</button>
            </div>
        </div>
    </div>
</div>

TypeScript (with just the code, no imports)

private initForm() {
    let recipeName = '';
    let recipeImagePath = '';
    let recipeDescription = '';
    let recipeIngredients = new FormArray([]);

    if(this.editMode) {
        const recipe = this.recipeService.getRecipe(this.id);
        recipeName = recipe.name;
        recipeImagePath = recipe.imagePath;
        recipeDescription = recipe.description;
        if(recipe['ingredients']) {
            for (const ingredient of recipe['ingredients']) {
                recipeIngredients.push(new FormGroup({
                    'name': new FormControl(ingredient.name, Validators.required),
                    'amount': new FormControl(ingredient.amount, [Validators.required, Validators.pattern(/^[1-9]+[0-9]*$/)])
                }));
            }
        }
    }

    this.recipeForm = new FormGroup({
        'name': new FormControl(recipeName, Validators.required),
        'imagePath': new FormControl(recipeImagePath, Validators.required),
        'description': new FormControl(recipeDescription, Validators.required),
        'ingredients': recipeIngredients
    })
}

getControls() {
    return (<FormArray>this.recipeForm.get('ingredients'))?.controls;
}

onAddIngredient() {
    (<FormArray>this.recipeForm.get('ingredients'))?.push({
        'name': new FormControl(null, Validators.required),
        'amount': new FormControl(null, [Validators.required, Validators.pattern(/^[1-9]+[0-9]*$/)])
    })
}

View and errors

enter image description here

Any idea on how to fix this?


Solution

  • In onAddIngredient method, you should add the FormGroup instance into FormArray but your existing code is adding an object into FormArray.

    onAddIngredient() {
      let fg: FormGroup<any> = new FormGroup({
        name: new FormControl(null, Validators.required),
        amount: new FormControl(null, [
          Validators.required,
          Validators.pattern(/^[1-9]+[0-9]*$/),
        ]),
      });
    
      (<FormArray>this.recipeForm.get('ingredients'))?.push(fg);
    }
    

    Demo @ StackBlitz