ExpressionChangedAfterItHasBeenCheckedError, ngForm inside ng-template or structural directives and bindings to this form outside of ngTemplate : change detection works incorrectly
See original GitHub issueπ bug report
Affected Package
The issue is caused by package (probably) `@angular/compiler`/`@angular/forms`/`@angular/common`Is this a regression?
I am not sure. I have 7.2.7+ (also represented in 7.2.10).
Description
A clear and concise description of the problem...What I have:
I have some wrapper with ngForm directive on it. Inside of this block with ngForm I have another wrapper with *ngIf directive. I have 2 inputs: type text and type checkbox in some container with *ngIf. Input type=text is dynamically required. It is required when checkbox is checked and otherwise. Inside ngForm wrapper, but outside of *ngIf wrapper I have 2 buttons: one button is native HTML button and another button is native button wrapped into my custom component. This component contains only native HTML button and it has disabled binding on it. Disabled binding applies as disabled attribute binding to native HTML button in it. Both native button and custom component button have absolutely same disabled
binding.
Common logic: buttons must be disabled when form is invalid and they must be enabled when form is invalid.
What I have: when I press checkbox form becomes invalid and native HTML button with disabled binding becomes disabled. But my custom button with disabled binding is not disabled. Also I have ExpressionChangedAfterItHasBeenCheckedError
error in console in dev mode.
π¬ Minimal Reproduction
[Stackblitz example](https://stackblitz.com/edit/angular-2cpkeo)- Open example
- Press checbox (set it to checked).
Expect: 2 buttons disabled (accordingly to all bindings) + no errors in console.
Fact: native HTML button disabled, but my custom control with disabled binding is not disabled + ExpressionChangedAfterItHasBeenCheckedError
error in console.
Notice: after next change detection cycle everything will become ok (you can trigger it by clicking anywhere outside of controls in my demo).
π₯ Exception or Error
ExpressionChangedAfterItHasBeenCheckedError: Expression has changed after it was checked. Previous value: 'disabled: true'. Current value: 'disabled: false'.
- visually state rendered incorrecly.
π Your Environment
Angular Version:
7.2.7 (also can be reproduced at 7.2.10).
Anything else relevant?
Thoughts about structural directives: Structural directives are compiled to ng-template
with directives. We figured out that it is not problem with structural directives. Structural directives are copiled to ng-templates. I also added raw ng-template
example to my tag. So it is not problem with ngIf/ngSwitch/ngForOf or any my project-specific structural directive. Looks like it is problem with ng-template
.
What I noticed: when I use ng-template
when @angular/compiler
creates ngfactory
for my component for some reasons it create not 1 factory function but more functions. For some reasons required
binding is in one factory, but buttons binding are in another factory (there are 2 βchange detectionβ functions in each factory). So approximate flow is:
- Call first βchange detectionβ function from βfirstβ ngfactory (with binding to native HTML button)
- Call βchange detectionβ function for required binding and change state of the form.
- Call second βchange detectionβ function from ngfactory from point 1 (βfirstβ ngfactory).
State of the form is changed in change detection cycle (at point 2) and when we reach point 3 we get another value from absolutely same binding. Because form state changed only at 2 point.
About error in console: In dev mode we have special check. After real change detection we have one more cycle to check if any bindings change their values. So in 1 point we got different values for disabled
expressions (because form state changed in 1 change detection cycle). Thats why we get this error.
I can write more verbose if you need. Hope you understood me.
Issue Analytics
- State:
- Created 5 years ago
- Reactions:8
- Comments:8 (2 by maintainers)
So any news on this? Is it just in backlog and would be fixed not rly soon? Looks like it is not even in backlog
This issue has been automatically locked due to inactivity. Please file a new issue if you are encountering a similar or related problem.
Read more about our automatic conversation locking policy.
This action has been performed automatically by a bot.