@@ -14,6 +14,9 @@ import {
14
14
EnvironmentInjector ,
15
15
NgZone ,
16
16
afterNextRender ,
17
+ afterRender ,
18
+ untracked ,
19
+ AfterRenderRef ,
17
20
} from '@angular/core' ;
18
21
import { Location } from '@angular/common' ;
19
22
import { Observable , Subject , merge , SubscriptionLike , Subscription } from 'rxjs' ;
@@ -60,6 +63,10 @@ export class OverlayRef implements PortalOutlet {
60
63
/** Stream of mouse outside events dispatched to this overlay. */
61
64
readonly _outsidePointerEvents = new Subject < MouseEvent > ( ) ;
62
65
66
+ private _renders = new Subject < void > ( ) ;
67
+
68
+ private _afterRenderRef : AfterRenderRef ;
69
+
63
70
constructor (
64
71
private _portalOutlet : PortalOutlet ,
65
72
private _host : HTMLElement ,
@@ -79,6 +86,15 @@ export class OverlayRef implements PortalOutlet {
79
86
}
80
87
81
88
this . _positionStrategy = _config . positionStrategy ;
89
+
90
+ this . _afterRenderRef = untracked ( ( ) =>
91
+ afterRender (
92
+ ( ) => {
93
+ this . _renders . next ( ) ;
94
+ } ,
95
+ { injector : this . _injector } ,
96
+ ) ,
97
+ ) ;
82
98
}
83
99
84
100
/** The overlay's HTML element */
@@ -223,7 +239,7 @@ export class OverlayRef implements PortalOutlet {
223
239
224
240
// Keeping the host element in the DOM can cause scroll jank, because it still gets
225
241
// rendered, even though it's transparent and unclickable which is why we remove it.
226
- this . _detachContentWhenStable ( ) ;
242
+ this . _detachContentWhenEmpty ( ) ;
227
243
this . _locationChanges . unsubscribe ( ) ;
228
244
this . _outsideClickDispatcher . remove ( this ) ;
229
245
return detachmentResult ;
@@ -256,6 +272,8 @@ export class OverlayRef implements PortalOutlet {
256
272
}
257
273
258
274
this . _detachments . complete ( ) ;
275
+ this . _afterRenderRef . destroy ( ) ;
276
+ this . _renders . complete ( ) ;
259
277
}
260
278
261
279
/** Whether the overlay has attached content. */
@@ -491,15 +509,15 @@ export class OverlayRef implements PortalOutlet {
491
509
}
492
510
493
511
/** Detaches the overlay content next time the zone stabilizes. */
494
- private _detachContentWhenStable ( ) {
512
+ private _detachContentWhenEmpty ( ) {
495
513
// Normally we wouldn't have to explicitly run this outside the `NgZone`, however
496
514
// if the consumer is using `zone-patch-rxjs`, the `Subscription.unsubscribe` call will
497
515
// be patched to run inside the zone, which will throw us into an infinite loop.
498
516
this . _ngZone . runOutsideAngular ( ( ) => {
499
517
// We can't remove the host here immediately, because the overlay pane's content
500
518
// might still be animating. This stream helps us avoid interrupting the animation
501
519
// by waiting for the pane to become empty.
502
- const subscription = this . _ngZone . onStable
520
+ const subscription = this . _renders
503
521
. pipe ( takeUntil ( merge ( this . _attachments , this . _detachments ) ) )
504
522
. subscribe ( ( ) => {
505
523
// Needs a couple of checks for the pane and host, because
0 commit comments