on loading of my parent component, i am updating the form of that (parent) component by using patchValue.
on of that form components i my child ControlValueAccessor component that also has a formgroup. therefore, on my writeValue function i am updating the child component regarding the value that passed from the parent component patchValue.
my writeValue function looks like that:
writeValue(value: CountryAndCity): void {
if (value != null && value.country && value.city) {
this.isDefaultValueDefined = true;
this.form.patchValue({country: value.country});
this.form.patchValue({city: value.city});
**this.cdRef.detectChanges();**
}
}
As you can see, i had to use detectChanges() as the last line of the above function because without it i am getting the error:
ParentComponent.html:1 ERROR Error: ExpressionChangedAfterItHasBeenCheckedError: Expression has changed after it was checked. Previous value: 'ng-pristine: true'. Current value: 'ng-pristine: false'.
i think i understand why is that. Angular start the check of the parent component, then, start to check the child component but then, on the child component the child component, on the writeValue function changing the parent component form state.
i feel uncomfortable with the use of detectChanges(). is there a way to do something else? is it a must when using parent and child components that each of them has formGroup and the child component is one of the parent formgroup formControl?
I don't think, that this is happening because of your write
function but rather that something in your form is emitting values right after the child has been created, but it is hard to tell without seeing more of your code.
I had the same problem so what I did to prevent this error without manually triggering change detection was to decouple the value propagation to the parent from the current change detection cycle.
An easy way to achieve this is to yield
in the value upstream like
this.form
.valueChanges
.pipe(
delay(0)
)
.subscribe(it => {
this.propagateChange(...)
})
I do not know if this is the best approach but for me it works.
BTW: I would also recommend using {emitEvent: false}
as patch options, which prevents the child from firing the event in the write
function. This would solve your problem if your assumption about the source of the error is true, but wouldn't if my assumption was true.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With