KayIcee
KayIcee

Reputation: 9

How do I get access to the controls of an item in FormArray?

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>

Upvotes: 0

Views: 2778

Answers (1)

Msk Satheesh
Msk Satheesh

Reputation: 1536

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 :)

Upvotes: 1

Related Questions