Reactive forms: mark dirty all controls in form group
Solution 1
If you have a complicated form structure, you can segregate the code to mark FormGroup
, FormArray
or FormControl
as dirty. See the example here : Mark Form as dirty
markDirty() {
this.markGroupDirty(this.form);
console.log('FORM:', this.form);}
markGroupDirty(formGroup: FormGroup) {
Object.keys(formGroup.controls).forEach(key => {
switch (formGroup.get(key).constructor.name) {
case "FormGroup":
this.markGroupDirty(formGroup.get(key) as FormGroup);
break;
case "FormArray":
this.markArrayDirty(formGroup.get(key) as FormArray);
break;
case "FormControl":
this.markControlDirty(formGroup.get(key) as FormControl);
break;
}
});
}
markArrayDirty(formArray: FormArray) {
formArray.controls.forEach(control => {
switch (control.constructor.name) {
case "FormGroup":
this.markGroupDirty(control as FormGroup);
break;
case "FormArray":
this.markArrayDirty(control as FormArray);
break;
case "FormControl":
this.markControlDirty(control as FormControl);
break;
}
});
}
markControlDirty(formControl: FormControl) {
formControl.markAsDirty();
}
Solution 2
Either mark the whole formGroup
as dirty:
this.form.markAsDirty();
Or mark each field:
Object.keys(this.form.controls).forEach(key => {
this.form.get(key).markAsDirty();
});
Solution 3
Best approach to do :
this will make every control dirty: this.form.markAsDirty();
Use this way (second option):
let controls = this.form.controls;
controls.forEach(control => {
this.form.get(control).markAsDirty();
});
Solution 4
mark as dirty controls(only those with value) inside FormGroup
markDirtyAllControlsWithValue(form: FormGroup): void {
const recursiveFunc = (formGroup: FormGroup) => {
Object.keys(formGroup.controls).forEach(field => {
const control = formGroup.get(field);
if (control.value !== null && control.value !== undefined && control.value !== '') {
control.markAsDirty();
}
if (control instanceof FormGroup) {
recursiveFunc(control);
}
});
};
recursiveFunc(form);
}
Solution 5
A simplified version of Sachin Gupta's solution:
public static markAllControlsAsDirty(abstractControls: AbstractControl[]): void {
abstractControls.forEach(abstractControl => {
if (abstractControl instanceof FormControl) {
(abstractControl as FormControl).markAsDirty({onlySelf: true});
} else if (abstractControl instanceof FormGroup) {
this.markAllControlsAsDirty(Object.values((abstractControl as FormGroup).controls));
} else if (abstractControl instanceof FormArray) {
this.markAllControlsAsDirty((abstractControl as FormArray).controls);
}
});
}
And use it like this:
FormUtils.markAllControlsAsDirty(Object.values(this.form.controls));
hofshteyn
Updated on July 22, 2022Comments
-
hofshteyn almost 2 years
I have Angular 6 app with form. Here is an examle
export class ExampleComponent implements OnInit { form: FormGroup; constructor(private fb: FormBuilder) { } ngOnInit() { this.form = new FormGroup({ first: new FormControl(), last: new FormControl() }); this.markControlsAsDirty(this.form); } markControlsAsDirty(form: FormGroup) { this.form.get('first').markAsDirty(); this.form.get('last').markAsDirty(); } }
I don't want to get a single control and mark every field. Can I mark all controls in form group as dirty?
UPDATE I've been added stackblitz example to show that two previous answers were wrong
-
hofshteyn about 5 years1 option: controls still pristine but form is dirty 2 option: linter error "control does not exist on type Abstract control"
-
hofshteyn about 5 yearscontrols still not dirty but form does
-
Roberto Zvjerković about 5 years
1 option: controls still pristine but form is dirty
That's literally what you asked for.2 option: linter error "control does not exist on type Abstract control"
Addif (control instanceof FormControl)
-
hofshteyn about 5 yearsI asked
Can I mark all controls in form group as dirty?
. Result is not that I expected -
hofshteyn about 5 yearsI added example in stackblitz, you can see in questions update.
-
Roberto Zvjerković about 5 yearsUpdated the answer.
-
argetlam5 over 4 yearsGood solution, though I do want to point out that in a production build, the constructor name is going to change/be uglified. Better to do an if/else if block where you check if it's an
instaceof
of the class.