1

I have an easy setup with Angular typed forms.
In the example I built a FormGroup with two FormControls:

  1. A normal text field with required Validators
  2. A form Array that contains a FormGroup with a single FormControl that is again just a text.

I also have two buttons where new FormGroups can be added/removed from the FormArray:

export class AppComponent {
  formGroup = this.fb.nonNullable.group({
    Name: ['', Validators.required],
    AppAssignments: this.fb.array(
      [] as FormGroup<{
        Name: FormControl<string | null>;
      }>[]
    ),
  });

  constructor(
    private fb: FormBuilder,
    public changeDetectorRef: ChangeDetectorRef
  ) {}

  public addAppAssignment() {
    this.formGroup.controls.AppAssignments.controls.push(
      this.fb.group({
        Name: new FormControl<string | null>(null, Validators.required),
      })
    );
    this.formGroup.updateValueAndValidity();
    this.changeDetectorRef.detectChanges();
  }
  public removeAppAssignment() {
    if (this.formGroup.controls.AppAssignments.length > 0) {
      this.formGroup.controls.AppAssignments.removeAt(
        this.formGroup.controls.AppAssignments.length - 1
      );
    }
  }
}

I am expecting the "Submit"-Button on the bottom of the form to be disabled/enabled depending on the status of the FormGroup.

However, adding Elements to the FormArray does not invalidate the FormControl.

When I debug the whole thing, I can see that after adding new FormControls to the FormArray, the FormArray is "VALID", even though some of the FormGroups inside are not valid anymore.

How can this be?

This Stackblitz demonstrates my problem.

5
  • Are you actually adding new controls all with the same name 'Name'? Commented Oct 14, 2024 at 14:54
  • Yes, look at my Blitz Commented Oct 14, 2024 at 14:59
  • Right, but that's one of the problems :D Controls need to have different names (you will have to create them dynamically). Commented Oct 14, 2024 at 15:02
  • I thought just a formgroup should have non duplicate names? So that's valid for the entire control? Do you have a reference? Commented Oct 14, 2024 at 15:46
  • Nope, duplicate entries seem to cause no problem. My solution works now with the modification from the accepted answer. Commented Oct 15, 2024 at 4:59

1 Answer 1

1

You need to use the push method on the control AppAssignments, that is what caused the bug.

Cause:

The push of FormArray might have additional logic added to it, for attaching controls, the AppAssignments.controls is just a regular array, whose push method, does not have this extra code, which might have caused the bug

Before:

this.formGroup.controls.AppAssignments.controls.push(
  ...
);

After:

this.formGroup.controls.AppAssignments.push(
  ...
);

Full Code:

import { ChangeDetectorRef, Component } from '@angular/core';
import {
  FormArray,
  FormBuilder,
  FormControl,
  FormGroup,
  Validators,
} from '@angular/forms';

interface FormModel {
  title: FormControl<string | null>;
  name: FormGroup<{
    firstName: FormControl<string | null>;
    lastName: FormControl<string | null>;
  }>;
  interest: FormArray<FormControl<string | null>>;
}

@Component({
  selector: 'my-app',
  templateUrl: './app.component.html',
  styleUrls: ['./app.component.css'],
})
export class AppComponent {
  formGroup = this.fb.nonNullable.group({
    Name: ['', Validators.required],
    AppAssignments: this.fb.array(
      [] as FormGroup<{
        Name: FormControl<string | null>;
      }>[]
    ),
  });

  constructor(
    private fb: FormBuilder,
    public changeDetectorRef: ChangeDetectorRef
  ) {}

  public addAppAssignment() {
    this.formGroup.controls.AppAssignments.controls.push(
      this.fb.group({
        Name: new FormControl<string | null>(null, Validators.required),
      })
    );
    this.formGroup.updateValueAndValidity();
    this.changeDetectorRef.detectChanges();
  }
  public removeAppAssignment() {
    if (this.formGroup.controls.AppAssignments.length > 0) {
      this.formGroup.controls.AppAssignments.removeAt(
        this.formGroup.controls.AppAssignments.length - 1
      );
    }
  }
}

Stackblitz Demo

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

3 Comments

What is actually the difference, if I am pushing "manuall" a new control to the controls array, or using the "push" method of the FormArray itself?
@DavidMason The push of FormArray might have additional logic added to it, for attaching controls, the AppAssignments.controls is just a regular array, whose push method, does not have this extra code, which might have caused the bug
Although this question has been answered well it can also be useful to be aware of the updateValueAndValidity Reactive Forms util that can be applied to a FormControl, FormArray or FormGroup after modification. (such as programmatically adding/removing a validation rule or disabling/enabling a control).

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.