angular: ExpressionChangedAfterItHasBeenCheckedError when changing a component value in afterViewInit
I’m submitting a …
[x] bug report
[ ] feature request
[ ] support request
Current behavior
changing a component value in afterViewInit throws ExpressionChangedAfterItHasBeenCheckedError
if the value has an impact on a method used in the view.
in the plunker:
-> getHeightPx()
returns 0px
before ngAfterViewInit is called (isLoaded === undefined
)
-> getHeightPx()
returns 100px
after ngAfterViewInit is called (isLoaded === true
)
Expected behavior
it should not throw the error since getHeightPx
is just a method and not part of the model.
Minimal reproduction of the problem with instructions http://plnkr.co/edit/JdhPkjBl6wc0FIc8LcUs?p=preview
- Angular version: 4.0.0-rc.0 => KO
- Angular version: 4.0.0-beta.8 => OK
About this issue
- Original URL
- State: closed
- Created 7 years ago
- Comments: 53 (25 by maintainers)
Commits related to this issue
- fix(core): don’t throw if queries change during change detection. This would be a breaking change compared to v2. Also discovered a bug with querying manually projected content, see #15117. Related ... — committed to tbosch/angular by tbosch 7 years ago
- fix(core): don’t throw if queries change during change detection. This would be a breaking change compared to v2. Also discovered a bug with querying manually projected content, see #15117. Related ... — committed to tbosch/angular by tbosch 7 years ago
- fix(core): don’t throw if queries change during change detection. This would be a breaking change compared to v2. Also discovered a bug with querying manually projected content, see #15117. Related ... — committed to tbosch/angular by tbosch 7 years ago
- fix(core): don’t throw if queries change during change detection. Throwing on query changes would be a breaking change compared to v2. Also discovers a bug with querying manually projected content, s... — committed to tbosch/angular by tbosch 7 years ago
- fix(core): don’t throw if queries change during change detection. Throwing on query changes would be a breaking change compared to v2. Also discovers a bug with querying manually projected content, s... — committed to tbosch/angular by tbosch 7 years ago
- fix(core): don’t throw if queries change during change detection. Throwing on query changes would be a breaking change compared to v2. Also discovers a bug with querying manually projected content, s... — committed to angular/angular by tbosch 7 years ago
- fix(core): don’t throw if queries change during change detection. Throwing on query changes would be a breaking change compared to v2. Also discovers a bug with querying manually projected content, s... — committed to SamVerschueren/angular by tbosch 7 years ago
- Found a dirty way to solve the ExpressionChangedAfterItHasBeenCheckedError. Look into: https://github.com/angular/angular/issues/14748 https://github.com/angular/angular/issues/15464 — committed to jfsebastian/FrontendExperiments by deleted user 7 years ago
- fix(core): don’t throw if queries change during change detection. Throwing on query changes would be a breaking change compared to v2. Also discovers a bug with querying manually projected content, s... — committed to asnowwolf/angular by tbosch 7 years ago
- fix(core): don’t throw if queries change during change detection. Throwing on query changes would be a breaking change compared to v2. Also discovers a bug with querying manually projected content, s... — committed to juleskremer/angular by tbosch 7 years ago
- Fix ExpressionChanged error by using AfterContentInit described in https://github.com/angular/angular/issues/14748 — committed to jackkoppa/cityaq by jackkoppa 6 years ago
it’s by design
On this similar issue, it is suggested that we run the change detection explicitly after the change. It works for me.
https://stackoverflow.com/questions/39787038/how-to-manage-angular2-expression-has-changed-after-it-was-checked-exception-w
I found 3 solutions for who are looking for easy fixes.
Moving from ngAfterViewInit to ngAfterContentInit
Moving to ngAfterViewChecked combined with ChangeDetectorRef as suggested on https://github.com/angular/angular/issues/14748#issuecomment-307291715
keep with
ngOnInit()
but call ChangeDetectorRef.detectChanges() after your changes.Hi all,
If this error is by design, what’s the correct pattern to avoid this sort of issue? I have an observable and I’m using as follows
The paging values will change once the data is loaded and the paging is calculated. It keep throwing that error on dev mode. In prod, that error does not appear. So I’m wondering what’s the correct pattern to avoid this issue.
Any help would be appreciated!
@victornoel comments without a Plunker that demonstrates the problem are not really helpful
was able to work around this be using ngDoCheck() method and calling the ChangeDetectorRef.detectChanges method.
You can inject
this.cdRef:ChangeDetectorRef
and then callthis.cdRef.detectChanges()
after you modified the model to work around the error.@TheBolmanator please refrain from making claims that are based on your limited Angular knowledge 😉 When you complain about Angular without exact instructions how to reproduce the problem, it’s IMHO safe to treat the comments as spam.
Hi all.
This is a helpful post to understand and fix this error.
Everything you need to know about the
ExpressionChangedAfterItHasBeenCheckedError
errorThat’s not true. It points out a possible error or architectural issue and it easy to fix There is no need to ignore it.
I also start to see ExpressionChangedAfterItHasBeenCheckedError after updating to 4.0.0-rc.1 from 4.0.0-beta.8 and 2.4.8.
https://plnkr.co/edit/atBNGvMgC3QxSGk7Sm6f?p=preview
Above plnkr shows Clarity’s datagrid without a problem with 4.0.0-beta.8. But, after commenting out beta.8 and uncommenting rc1 in the config.js file, this error is thrown.
ExpressionChangedAfterItHasBeenCheckedError: Expression has changed after it was checked. Previous value: ‘Query 3 not dirty’. Current value: ‘Query 3 dirty’.
Was there any breaking change regarding the above between beta.8 and rc.1? If I run it with enableProdMode(), the error disappears.
ping @youdz
ok is see the difference.
isViewInit
has an impact on the getTextDecoration method used in the view - via the ngStyle here) then it throws the error since 4.0.0-rc.1http://plnkr.co/edit/I51JWge8P5oY0mj2Ni65?p=preview
@pappacurds and @imransilvake That’s not a great solution, what your doing is telling angular to run change detection every time change detection has occured, in other words, you’ve created an infinite loop…
@zoechi clearly what @TheBolmanator is saying is that no, there is no easy fix!
In this thread we see a lot of unanswered questions about how to manage this… This one is a good example: https://github.com/angular/angular/issues/14748#issuecomment-300976768. It seems that some of the error disappear if you play with ngIf and as in order to change the way things are interpreted at runtime… I’m pretty sure this is neither an easy fix (hard to maintain) and not an architectural issue…
It is not clear what is the source of these errors (nor how to fix them). Yes, in some cases, the problem is clear and you need to force change detection, but for the rest, there is many cases where you have an async pipe that makes this problem appear with no reason whatsoever.
What is the appropriate place to update UI menu to avoid this error?
@sandraacha9 nu inteleg ce spui…
Hi All,
I was having this issue and it was bugging me for a long time. I think I finally found a pattern that is avoiding receiving this problem. It seems to be essentially a synchronization issue.
Approach one: use NGRX and start managing the state of the objects you are handling and getting this sort of issue. To implement this, find the many tutorials available on the internet. Imo, this approach is only good when you are managing state of many objects across many components. Otherwise it adds a development overhead that you need to evaluate if truly is worthwhile.
Approach two: create a simple service that manages the state of this object using BehaviorSubject.
For this approach, check this out.
So lets say you have a root component that is responsible to set the basic layout of the component and multiple sub-components that are basically different content but can re-use the root structure. The button Add new should only appear on the listing content and hide on edit mode.
The content received inside the
<router-outlet></router-outlet>
modifies the value of theshowButton
and throwing the annoying exception we are all seeing.Modified the showButton to the following:
<div class="heading-elements" *ngIf="addNewbuttonState$ | async">...</div>
Now that annoying message is no longer showing up and the load stays correct. Whenever you need to change the state of the button, simply inject the service and use the setter. Whatever component is subscribed to this Observable will get the update.
I hope this can help you all. Cheers
probably was a bug or it was disabled. anyway it throws in 2.x and it will throw in 4.x
@DzmitryShylovich humm indeed just saw it, but then why did that work in 4.0.0-beta.8 ? (and many previous version since the release)