question-mark
Stuck on an issue?

Lightrun Answers was designed to reduce the constant googling that comes with debugging 3rd party libraries. ItΒ collects links to all the places you might be looking at while hunting down a tough bug.

And, if you’re still stuck at the end, we’re happy to hop on a call to see how we can help out.

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)
  1. Open example
  2. 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:

  1. Call first β€œchange detection” function from β€œfirst” ngfactory (with binding to native HTML button)
  2. Call β€œchange detection” function for required binding and change state of the form.
  3. 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:closed
  • Created 5 years ago
  • Reactions:8
  • Comments:8 (2 by maintainers)

github_iconTop GitHub Comments

4reactions
sharikovvladislavcommented, Apr 2, 2019

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

0reactions
angular-automatic-lock-bot[bot]commented, Oct 4, 2020

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.

Read more comments on GitHub >

github_iconTop Results From Across the Web

NG0100: Expression has changed after it was checked - Angular
Angular throws an ExpressionChangedAfterItHasBeenCheckedError when an expression value has been changed after change detection has completed. Angular onlyΒ ...
Read more >
ngIf - Expression has changed after it was checked
The problem is that because the text changes when it is fetched, the 'expand' button's condition turns to true after Angular's change detection...
Read more >
ExpressionChangedAfterItHasBe...
The error arises when the binding expression changes after angular checked it during the change detection cycle. Table of Contents.
Read more >
Updating Angular Forms with patchValue or setValue
If you're still guessing which method to use to update a Reactive Form value in Angular, then this post is for you. It's...
Read more >
What Solution To Be Put To Remove A Ng-If Error - ADocLib
basically I have a form that has a validation of required according to certain Input invalid import {FormControl FormGroup Validators} from '@angular/forms'Β ...
Read more >

github_iconTop Related Medium Post

No results found

github_iconTop Related StackOverflow Question

No results found

github_iconTroubleshoot Live Code

Lightrun enables developers to add logs, metrics and snapshots to live code - no restarts or redeploys required.
Start Free

github_iconTop Related Reddit Thread

No results found

github_iconTop Related Hackernoon Post

No results found

github_iconTop Related Tweet

No results found

github_iconTop Related Dev.to Post

No results found

github_iconTop Related Hashnode Post

No results found