0

What I'm trying to do is to add an invalid class to the parent div of each input based on if its valid or not.

In the rest of the form I have access to the input field control like so:

<div
    class="form-group focus"
    [ngClass]="!recipeForm.controls.name.valid ? 'invalid' : ''"
  >
    <input
      type="text"
      id="name"
      class="form-control"
      formControlName="name"
    />
    <label for="name" class="shrink">Name</label>
  </div>

[ngClass]="!recipeForm.controls.name.valid ? 'invalid' : ''"

But then I have a FormsArray of ingredients with name/amount controls.How do I have access to those?`

  get controls() {
    // a getter!
    const FormArray = (<FormArray>this.recipeForm.get('ingredients')).controls;

    for (let i = 0; i < FormArray.length; i++) {
      console.log(FormArray[i]);
    }
    return FormArray;
  }`

If I do FormArray[i].value.name it works but If I do FormArray[i].controls.name it says Property 'controls' does not exist on type 'AbstractControl' even though I can see that there is a controls property with name and amount.

My ts file:

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

HTML template:

<div class="form-ingredients" formArrayName="ingredients">
  <div
    class="form-amount-group"
    *ngFor="let ingredientCtrl of controls; let i = index"
    [formGroupName]="i"
  >
    <div class="form-group focus">
      <input class="" type="text" id="name" class="form-control" />
      <label for="name" class="shrink">Name</label>
    </div>
    <div class="form-group focus amount">
      <input
        type="number"
        class="form-control"
        formControlName="amount"
      />
      <label for="name" class="shrink">Amount</label>
    </div>

    <div class="operations">
      <div class="button plus">
        <button><i class="fas fa-plus"></i></button>
      </div>
      <div class="button minus">
        <button><i class="fas fa-minus"></i></button>
      </div>
    </div>

    <button class="btn btn-sm" title="Delete Ingredient">
      <i class="fa fa-trash"></i>
    </button>
  </div>
</div>
3
  • can you share your formArray html Commented Feb 10, 2021 at 13:45
  • Yeah, added ts and html template just now :) Commented Feb 10, 2021 at 15:38
  • I have added the answer to your question. Commented Feb 10, 2021 at 16:30

1 Answer 1

1

Try using:

You looping through the controls.so, your looping element is the control.

app.component.ts

  get controls() {
    return (this.recipeForm.get("ingredients") as FormArray).controls;
  }

  addIngredient() {
    const creds = this.recipeForm.controls.ingredients as FormArray;
    creds.push(
      this.fb.group({
        name: [null, Validators.required],
        amount: [
          null,
          [Validators.required, Validators.pattern(/^[1-9]+[0-9]*$/)]
        ]
      })
    );
  }

app.component.html

<form [formGroup]="recipeForm">
  <input type="checkbox" formControlName="name" /> Published
  <div *ngIf="recipeForm.controls.name.value">
    <h2>ingredients</h2>
    <button (click)="addIngredient()">Add</button>
    <div formArrayName="ingredients">
      <div *ngFor="let ingredient of controls; let i = index">
        <div [formGroup]="ingredient">
          <input placeholder="Name" formControlName="name" />
          <p>{{ ingredient.get("name").valid }}</p>
          <input placeholder="Amount" formControlName="amount" />
          <p>{{ ingredient.get("amount").valid }}</p>
        </div>
      </div>
    </div>
  </div>
</form>

Here the working stackblitz example:

https://stackblitz.com/edit/angular-form-array-example-ewyumv?file=src/app/app.component.ts

Hope this helps :)

Sign up to request clarification or add additional context in comments.

4 Comments

I can get {{ ingredient.get("name") }} but if I do {{ ingredient.get("name").valid }} it says object is possibly null, why is that?
And if I add [formGroup]="ingredient" to the parent div its showing me this error
Type 'AbstractControl' is missing the following properties from type 'FormGroup': controls, registerControl, addControl, removeControl, and 3 more.
use different div's for ngFor and formGroup

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.