46

How do I mark an Angular 2 Control as dirty in my code?

When I do it like this:

control.dirty = true;

I get this error:

Cannot set property dirty of #<AbstractControl> which has only a getter
Eran Shabi
  • 14,201
  • 7
  • 30
  • 51

5 Answers5

98

You should use the markAsDirty method, like this:

control.markAsDirty();

This will also mark all direct ancestors as dirty to maintain the model.

Docs link

Eran Shabi
  • 14,201
  • 7
  • 30
  • 51
6

Assuming that you call the method from your template as:

<form #loginForm = "ngForm" (ngSubmit)="login(loginForm)"> ... </form>

In your login.component.ts, use the following

login(loginForm : any) {
    //make sure that inputs are valid
    if (loginForm.invalid) { 
      Object.keys( loginForm.controls).forEach(key => {
       loginForm.controls[key].markAsDirty();
      });
      return;
    }
}
Yazan Khalaileh
  • 589
  • 6
  • 15
3

You can write a custom function to mark all the controls in a FormGroup as touched/dirty like this:

  markFormGroupTouched(formGroup: FormGroup) {
    (<any>Object).values(formGroup.controls).forEach(control => {
      control.markAsDirty();  // or control.markAsTouched();
    });
  }
BlackBeard
  • 10,246
  • 7
  • 52
  • 62
1

For template driven forms we can use below generic code

 public onSubmitForm(cardFormObject: NgForm) {
        if (!cardFormObject.valid)
            this.markAsDerty(cardFormObject);      

    }

    private markAsDerty(cardFormObject: NgForm) {
        for (var eachControl in cardFormObject.controls) {
            (<FormControl>cardFormObject.controls[eachControl]).markAsDirty();
        }
    }
0

If you are looking for marking dirty all the controls inside a form

Create a utils file for forms and export from there the following function

/**
 * Marks all the controls and their nested controls as dirty.
 * @param abstractControls - an array of controls(can be FormControls, FormGroups or FormArrays)
 */
export function markAllControlsAsDirty(abstractControls: AbstractControl[]): void {
  abstractControls.forEach((abstractControl) => {
    if (abstractControl instanceof FormControl) {
      (abstractControl as FormControl).markAsDirty({ onlySelf: true });
    } else if (abstractControl instanceof FormGroup) {
      markAllControlsAsDirty(
        Object.values((abstractControl as FormGroup).controls)
      );
    } else if (abstractControl instanceof FormArray) {
      markAllControlsAsDirty((abstractControl as FormArray).controls);
    }
  });
}

After that you can just call the function anywhere in the app like this:

markAllControlsAsDirty([form]);