'Angular Reactive Forms AddControl Causes ExpressionChangedAfterItHasBeenCheckedError When Using PatchValue
I wanted to be able to build up a reactive form using components, but not set it all up in a single parent component. So I created the intial FormGroup
and passed it to the components, which then do this.form.addControl(this.fb.group({ ... }));
to add their group to the form.
Example
Parent Component
this.form = this.fb.group({}); // Empty
public ngAfterViewInit() {
// Throws error after trying to patchValue on the child component
this.form.get('example').patchValue({
field1: 'Hello World!'
});
}
Child Components
this.parentFormGroup.addControl(
'childGroup',
this.fb.group({
field1: [
'', [Validators.required]
],
etc...
}
);
This works until I try and this.form.get('childGroup').patchValue({ ... })
after making a request in the ngAfterViewInit
lifecycle hook of the parent component. Instead of patching the group it throws an:
ERROR Error: ExpressionChangedAfterItHasBeenCheckedError: Expression has
changed after it was checked. Previous value: 'ng-valid: false'. Current value:
'ng-valid: true'.
Is there a way to have child components add themselves to a FormGroup
, and not have the parent setup the FormGroup
controls and validations. We need to reuse the child components in different ways and combinations within the application so didn't want to keep repeating the FormGroup
declaration outside of the child components, but this doesn't seem to work.
Solution 1:[1]
This error appears, because by patching the value in ngAfterViewInit you change the validity state of the form after the form has already been checked by the Angular change detection logic.
You have two options to prevent it:
- You set up the form in a way to have directly the right validity state, e.g. by passing the initial value to the child and setting it there
or
You move setting the value to another change detection cycle by wrapping the patchValue into a setTimeout:
setTimeout(() => this.form.get('childGroup').patchValue({ ... }))
Sources
This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.
Source: Stack Overflow
Solution | Source |
---|---|
Solution 1 | slim |