Reputation: 1272
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
Upvotes: 17
Views: 27676
Reputation: 63
I will post update for who is using Angular18+ based on @Sachin Gupta answer.
His solution wasn't working for me till I found out constructor.name
on FormControl
was returning FormControl2
(idk why).
So this is my util class:
import { AbstractControl, FormArray, FormControl, FormGroup } from "@angular/forms";
export class FMWFormControlUtils {
static isValid(control: AbstractControl) {
return control.valid
&& !control.pristine
&& (control.touched)
&& control.status != 'DISABLED'
&& control.status != 'PENDING';
}
static markGroupDirty(formGroup: FormGroup) {
Object.keys(formGroup.controls).forEach((key) => {
const name = formGroup.get(key)!.constructor.name;
if (name.includes('FormGroup')) {
this.markGroupDirty(formGroup.get(key) as FormGroup);
}
if (name.includes('FormArray')) {
this.markArrayDirty(formGroup.get(key) as FormArray);
}
if (name.includes('FormControl')) {
this.markControlDirty(formGroup.get(key) as FormControl);
}
});
}
static markArrayDirty(formArray: FormArray) {
formArray.controls.forEach((control) => {
const name = control.constructor.name
if (name.includes('FormGroup')) {
this.markGroupDirty(control as FormGroup);
}
if (name.includes('FormArray')) {
this.markArrayDirty(control as FormArray);
}
if (name.includes('FormControl')) {
this.markControlDirty(control as FormControl);
}
});
}
static markControlDirty(formControl: FormControl) {
formControl.markAsDirty();
}
}
Upvotes: 0
Reputation: 10127
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();
});
Upvotes: 14
Reputation: 5301
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();
}
Upvotes: 14
Reputation: 31
A even-better version of Nicolas Ay's solution:
Create a utils file for forms and export from there Nicolas's solution
/**
* 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]);
Upvotes: 3
Reputation: 901
The current version (12) has markAllAsTouched but not markAllAsDirty on the abstractControl.
This is my example that sets dirty to all formControls:
export function markAllAbstractDirty<T extends AbstractControl>(control: T): void {
if (control instanceof FormGroup) {
const controls = control.controls;
Object.keys(controls).forEach(key => {
controls[key].markAsDirty();
markAllAbstractDirty(controls[key]);
});
} else if (control instanceof FormArray) {
control.controls.forEach(formControl => formControl.markAsDirty());
} else if (control instanceof FormControl) {
control.markAsDirty();
} else {
throw new Error('Error: unexpected control value');
}
}
Upvotes: 1
Reputation: 71
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));
Upvotes: 5
Reputation: 841
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);
}
Upvotes: 1
Reputation: 1767
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();
});
Upvotes: 3