I'm submitting a ... (check one with "x")
[x] bug report => Search github for a similar issue or PR before submitting
[ ] feature request => Please check if request is not on the roadmap already https://github.com/primefaces/primeng/wiki/Roadmap
[ ] support request => Please do not submit support request here, instead see http://forum.primefaces.org/viewforum.php?f=35
Plunkr Case (Bug Reports)
https://stackblitz.com/edit/github-6dh6gj-rwjkmq
Current behavior
However component still works but errors are thrown which is problematic in application with dedicated error handling.
Thrown errors:
ERROR Error: ExpressionChangedAfterItHasBeenCheckedError: Expression has changed after it was checked. Previous value: 'ngIf: true'. Current value: 'ngIf: false'.
ERROR TypeError: Cannot read property 'offsetHeight' of null
Expected behavior
No errors are thrown in console
Minimal reproduction of the problem with instructions
Case 1.
Case 2.
What is the motivation / use case for changing the behavior?
Usage ofoverlay panel shouldn't produce errors
Angular version: 9.1.4
PrimeNG version: 9.0.6
Browser: [all]
Found fix editing node_module files. The problem seems to be that this.render = false is called in a wrong place. When new cycle begins, the old one is not finished yet then old cycle changes this.render value when new cycle began with different value which causes angular crash with ERROR Error: ExpressionChangedAfterItHasBeenCheckedError: Expression has changed after it was checked. Previous value: 'ngIf: true'. Current value: 'ngIf: false'
onAnimationEnd(event) {
switch (event.toState) {
case 'void':
if (this.destroyCallback) {
this.destroyCallback();
this.destroyCallback = null;
}
break;
case 'close':
this.onContainerDestroy();
this.onHide.emit({});
// REMOVED: this.render =false;
break;
}
}
hide() {
// ADDED
this.render = false;
this.overlayVisible = false;
}
In case anyone face this problem i have temporary solved it by injecting service to module constructor where i use OverlayPanel. Service looks like:
@Injectable()
export class PrimeNGCorrectionService {
init() {
this.installOverlayPanelFix();
}
private installOverlayPanelFix() {
OverlayPanel.prototype.hide = function (this: OverlayPanel) {
this.render = false;
this.overlayVisible = false;
};
const onAnimationEndSource: Function = OverlayPanel.prototype.onAnimationEnd;
OverlayPanel.prototype.onAnimationEnd = function (this: OverlayPanel, event: any) {
onAnimationEndSource.call(this, event);
if (event.toState === "close") {
this.render = true;
}
};
}
}
Just to add to this a more complete stacktrace:

core.js:6228 ERROR Error: ExpressionChangedAfterItHasBeenCheckedError: Expression has changed after it was checked. Previous value: 'true'. Current value: 'false'.
at throwErrorIfNoChangesMode (core.js:8147)
at bindingUpdated (core.js:20136)
at Module.傻傻property (core.js:21163)
at OverlayPanel_Template (primeng-overlaypanel.js:221)
at executeTemplate (core.js:12156)
at refreshView (core.js:11995)
at refreshComponent (core.js:13445)
at refreshChildComponents (core.js:11716)
at refreshView (core.js:12051)
at refreshEmbeddedViews (core.js:13391)
defaultErrorLogger @ core.js:6228
handleError @ core.js:6281
(anonymous) @ core.js:43145
invoke @ zone-evergreen.js:364
run @ zone-evergreen.js:123
runOutsideAngular @ core.js:41488
tick @ core.js:43142
(anonymous) @ core.js:42975
invoke @ zone-evergreen.js:364
onInvoke @ core.js:41654
invoke @ zone-evergreen.js:363
run @ zone-evergreen.js:123
run @ core.js:41427
next @ core.js:42971
schedulerFn @ core.js:37119
__tryOrUnsub @ Subscriber.js:183
next @ Subscriber.js:122
_next @ Subscriber.js:72
next @ Subscriber.js:49
next @ Subject.js:39
emit @ core.js:37079
checkStable @ core.js:41566
onLeave @ core.js:41729
onInvokeTask @ core.js:41638
invokeTask @ zone-evergreen.js:398
runTask @ zone-evergreen.js:167
invokeTask @ zone-evergreen.js:480
invokeTask @ zone-evergreen.js:1621
globalZoneAwareCallback @ zone-evergreen.js:1647
core.js:6228 ERROR TypeError: Cannot read property 'offsetHeight' of null
at Function.absolutePosition (primeng-dom.js:113)
at OverlayPanel.align (primeng-overlaypanel.js:143)
at OverlayPanel.onAnimationStart (primeng-overlaypanel.js:157)
at OverlayPanel_div_0_Template_div_animation_animation_start_0_listener (primeng-overlaypanel.js:28)
at executeListenerWithErrorHandling (core.js:21806)
at wrapListenerIn_markDirtyAndPreventDefault (core.js:21848)
at animations.js:394
at Array.forEach (<anonymous>)
at animations.js:388
at ZoneDelegate.invoke (zone-evergreen.js:364)
same issue
In case anyone face this problem i have temporary solved it by injecting service to module constructor where i use OverlayPanel. Service looks like:
@Injectable() export class PrimeNGCorrectionService { init() { this.installOverlayPanelFix(); } private installOverlayPanelFix() { OverlayPanel.prototype.hide = function (this: OverlayPanel) { this.render = false; this.overlayVisible = false; }; const onAnimationEndSource: Function = OverlayPanel.prototype.onAnimationEnd; OverlayPanel.prototype.onAnimationEnd = function (this: OverlayPanel, event: any) { onAnimationEndSource.call(this, event); if (event.toState === "close") { this.render = true; } }; } }
Thank you for your fix.
Even with it, I was still getting crashes but it gives me a good starting point. Please find below what I added to make it works for me.
`/* modules */
import { Injectable } from '@angular/core';
/* feature modules */
import { OverlayPanel } from 'primeng';
@Injectable({
providedIn: 'root',
})
export class PrimeNgOverlayPanelFixService {
constructor() {
this.installOverlayPanelFix();
}
private installOverlayPanelFix() {
const onAlignSource: Function = OverlayPanel.prototype.align;
OverlayPanel.prototype.align = function (this: OverlayPanel) {
var _this = this;
if (_this.container != null && _this.target != null) {
onAlignSource.call(_this);
}
};
const onBindDocumentClickListenerSource: Function = OverlayPanel.prototype.bindDocumentClickListener;
OverlayPanel.prototype.bindDocumentClickListener = function (this: OverlayPanel) {
var _this = this;
if (_this.container != null && _this.target != null) {
onBindDocumentClickListenerSource.call(_this);
}
};
OverlayPanel.prototype.hide = function (this: OverlayPanel) {
var _this = this;
_this.render = false;
_this.overlayVisible = false;
};
const onAnimationEndSource: Function = OverlayPanel.prototype.onAnimationEnd;
OverlayPanel.prototype.onAnimationEnd = function (this: OverlayPanel, event: any) {
var _this = this;
onAnimationEndSource.call(_this, event);
if (event.toState === "close") {
_this.render = true;
}
};
}
}`
In case anyone face this problem i have temporary solved it by injecting service to module constructor where i use OverlayPanel. Service looks like:
@Injectable() export class PrimeNGCorrectionService { init() { this.installOverlayPanelFix(); } private installOverlayPanelFix() { OverlayPanel.prototype.hide = function (this: OverlayPanel) { this.render = false; this.overlayVisible = false; }; const onAnimationEndSource: Function = OverlayPanel.prototype.onAnimationEnd; OverlayPanel.prototype.onAnimationEnd = function (this: OverlayPanel, event: any) { onAnimationEndSource.call(this, event); if (event.toState === "close") { this.render = true; } }; } }
It fixes the issue but it breaks the onHide event, it doesn't get triggered anymore. In my code I have something like this:
...
...
@tadamczak after adding your fix "resetAddFilterForm" is not triggered anymore when the OverlayPanel is closed.
In case anyone face this problem i have temporary solved it by injecting service to module constructor where i use OverlayPanel. Service looks like:
@Injectable() export class PrimeNGCorrectionService { init() { this.installOverlayPanelFix(); } private installOverlayPanelFix() { OverlayPanel.prototype.hide = function (this: OverlayPanel) { this.render = false; this.overlayVisible = false; }; const onAnimationEndSource: Function = OverlayPanel.prototype.onAnimationEnd; OverlayPanel.prototype.onAnimationEnd = function (this: OverlayPanel, event: any) { onAnimationEndSource.call(this, event); if (event.toState === "close") { this.render = true; } }; } }It fixes the issue but it breaks the onHide event, it doesn't get triggered anymore. In my code I have something like this:
...
(onHide)="resetAddFilterForm()">
...@tadamczak after adding your fix "resetAddFilterForm" is not triggered anymore when the OverlayPanel is closed.
You are right @tadamczak I spotted it too. I was planning to work on it after my holidays. But feel free to solve it ;)
Here what I did and it seems to solve the issue breaking the onHide event.
const onAnimationEndSource: Function = OverlayPanel.prototype.onAnimationEnd;
OverlayPanel.prototype.onAnimationEnd = function (this: OverlayPanel, event: any) {
const _this = this;
onAnimationEndSource.call(_this, event);
if (event.toState === 'close') {
/* this.render = true;*/
(<any>_this).cd.detectChanges();
}
};
when i use the mouseover event, it occurs the same error. in my case, I use the OverlayPanel in a list, using the mouseenter event to open, hovering the mouse over the label to open the list, when I release the mouse from the top, it occurs the ExpressionChangedAfterItHasBeenCheckedError error.
if i used the service you passed above, would it solve the problem?

when i use the mouseover event, it occurs the same error. in my case, I use the OverlayPanel in a list, using the mouseenter event to open, hovering the mouse over the label to open the list, when I release the mouse from the top, it occurs the ExpressionChangedAfterItHasBeenCheckedError error.
if i used the service you passed above, would it solve the problem?
It should. The ExpressionChangedAfterItHasBeenCheckedError error occurs because the internal variable "render" is set by the onAnimationEnd method to true value after being checked by angular with false value
Hi @tadamczak ,
I have the same error :
ERROR TypeError: Cannot read property 'offsetHeight' of null
when using the OverlayPanel on mouseenter and mouseleave event when I was switching fast between cells of my table.
I managed to avoid throwing this error by using the following code:
// in your your .ts file
showOverlayPanel(event) {
if (this.overlayPanel.target === null || this.overlayPanel.target === undefined) {
this.overlayPanel.show(event);
}
}
<!-- in your your .html file -->
md5-28c60b97228b0c1b95801685e4f995fe
Hope it will help
Unable to replicate with PrimeNG 11.0.0-rc.1, if the issue persists please create a new ticket with a test case reproducing the issue e.g. stackblitz or a github repo and it will be reviewed by our team once again.
Still happens for me, seems to me the listener that checks if the click happened outside fires way too fast, and thus the second time around the dialog never opens. I copied the raw source for now and modified the onAnimationStart event to the following:
(added the setTimeout)
onAnimationStart(event: AnimationEvent) {
if (event.toState === 'open') {
setTimeout(() => {
this.container = event.element;
this.onShow.emit(null);
this.appendContainer();
this.align();
this.bindDocumentClickListener();
this.bindDocumentResizeListener();
this.bindScrollListener();
if (this.focusOnShow) {
this.focus();
}
});
}
}
That made it work for me.
Just a note: still occurs (2021-1-19; with primeng 9.0.5)
Same issue version 11.4.0
Unable to replicate with PrimeNG 11.0.0-rc.1, if the issue persists please create a new ticket with a test case reproducing the issue e.g. stackblitz or a github repo and it will be reviewed by our team once again.
Please reopen this issue
Issue reproduction
Angular 11 PrimeNg 11.4.0
The link show the behavior. Open the console and hover the text. Should see:
Error: ExpressionChangedAfterItHasBeenCheckedError: Expression has changed after it was checked. Previous value: 'ngIf: true'. Current value: 'ngIf: false'.
at viewDebugError (vendor.js:46667)
at expressionChangedAfterItHasBeenCheckedError (vendor.js:46655)
at checkBindingNoChanges (vendor.js:46865)
at checkNoChangesNodeInline (vendor.js:55242)
at checkNoChangesNode (vendor.js:55231)
at debugCheckNoChangesNode (vendor.js:55828)
at debugCheckDirectivesFn (vendor.js:55760)
at Object.updateDirectives (default~pages-_searchs-interview-test-interview-test-module-ngfactory~pages-member-member-module-ngfactory.js:1317)
at Object.debugUpdateDirectives [as updateDirectives] (vendor.js:55753)
at checkNoChangesView (vendor.js:55130)
In case anyone face this problem i have temporary solved it by injecting service to module constructor where i use OverlayPanel. Service looks like:
@Injectable() export class PrimeNGCorrectionService { init() { this.installOverlayPanelFix(); } private installOverlayPanelFix() { OverlayPanel.prototype.hide = function (this: OverlayPanel) { this.render = false; this.overlayVisible = false; }; const onAnimationEndSource: Function = OverlayPanel.prototype.onAnimationEnd; OverlayPanel.prototype.onAnimationEnd = function (this: OverlayPanel, event: any) { onAnimationEndSource.call(this, event); if (event.toState === "close") { this.render = true; } }; } }
I managed to fix the onHide event by adding the original lines of code in the rewritten hide method (primeng 11.4.0):
@Injectable()
export class PrimeNGCorrectionService {
init() {
this.installOverlayPanelFix();
}
private installOverlayPanelFix() {
OverlayPanel.prototype.hide = function (this: OverlayPanel) {
this.overlayVisible = false;
this.cd.markForCheck();
this.render = false;
this.overlayVisible = false;
};
const onAnimationEndSource: Function = OverlayPanel.prototype.onAnimationEnd;
OverlayPanel.prototype.onAnimationEnd = function (this: OverlayPanel, event: any) {
onAnimationEndSource.call(this, event);
if (event.toState === "close") {
this.render = true;
}
};
}
}
Most helpful comment
Issue reproduction
Angular 11 PrimeNg 11.4.0
The link show the behavior. Open the console and hover the text. Should see:
Error: ExpressionChangedAfterItHasBeenCheckedError: Expression has changed after it was checked. Previous value: 'ngIf: true'. Current value: 'ngIf: false'.
at viewDebugError (vendor.js:46667)
at expressionChangedAfterItHasBeenCheckedError (vendor.js:46655)
at checkBindingNoChanges (vendor.js:46865)
at checkNoChangesNodeInline (vendor.js:55242)
at checkNoChangesNode (vendor.js:55231)
at debugCheckNoChangesNode (vendor.js:55828)
at debugCheckDirectivesFn (vendor.js:55760)
at Object.updateDirectives (default~pages-_searchs-interview-test-interview-test-module-ngfactory~pages-member-member-module-ngfactory.js:1317)
at Object.debugUpdateDirectives [as updateDirectives] (vendor.js:55753)
at checkNoChangesView (vendor.js:55130)