@@ -186,25 +186,9 @@ export class OverlayRef implements PortalOutlet, OverlayReference {
186
186
// Remove this overlay from keyboard dispatcher tracking.
187
187
this . _keyboardDispatcher . remove ( this ) ;
188
188
189
- // Keeping the host element in DOM the can cause scroll jank, because it still gets rendered,
190
- // even though it's transparent and unclickable. We can't remove the host here immediately,
191
- // because the overlay pane's content might still be animating. This stream helps us avoid
192
- // interrupting the animation by waiting for the pane to become empty.
193
- const subscription = this . _ngZone . onStable
194
- . asObservable ( )
195
- . pipe ( takeUntil ( merge ( this . _attachments , this . _detachments ) ) )
196
- . subscribe ( ( ) => {
197
- // Needs a couple of checks for the pane and host, because
198
- // they may have been removed by the time the zone stabilizes.
199
- if ( ! this . _pane || ! this . _host || this . _pane . children . length === 0 ) {
200
- if ( this . _host && this . _host . parentElement ) {
201
- this . _previousHostParent = this . _host . parentElement ;
202
- this . _previousHostParent . removeChild ( this . _host ) ;
203
- }
204
-
205
- subscription . unsubscribe ( ) ;
206
- }
207
- } ) ;
189
+ // Keeping the host element in DOM the can cause scroll jank, because it still gets
190
+ // rendered, even though it's transparent and unclickable which is why we remove it.
191
+ this . _detachContentWhenStable ( ) ;
208
192
209
193
return detachmentResult ;
210
194
}
@@ -425,6 +409,33 @@ export class OverlayRef implements PortalOutlet, OverlayReference {
425
409
isAdd ? classList . add ( cssClass ) : classList . remove ( cssClass ) ;
426
410
} ) ;
427
411
}
412
+
413
+ /** Detaches the overlay content next time the zone stabilizes. */
414
+ private _detachContentWhenStable ( ) {
415
+ // Normally we wouldn't have to explicitly run this outside the `NgZone`, however
416
+ // if the consumer is using `zone-patch-rxjs`, the `Subscription.unsubscribe` call will
417
+ // be patched to run inside the zone, which will throw us into an infinite loop.
418
+ this . _ngZone . runOutsideAngular ( ( ) => {
419
+ // We can't remove the host here immediately, because the overlay pane's content
420
+ // might still be animating. This stream helps us avoid interrupting the animation
421
+ // by waiting for the pane to become empty.
422
+ const subscription = this . _ngZone . onStable
423
+ . asObservable ( )
424
+ . pipe ( takeUntil ( merge ( this . _attachments , this . _detachments ) ) )
425
+ . subscribe ( ( ) => {
426
+ // Needs a couple of checks for the pane and host, because
427
+ // they may have been removed by the time the zone stabilizes.
428
+ if ( ! this . _pane || ! this . _host || this . _pane . children . length === 0 ) {
429
+ if ( this . _host && this . _host . parentElement ) {
430
+ this . _previousHostParent = this . _host . parentElement ;
431
+ this . _previousHostParent . removeChild ( this . _host ) ;
432
+ }
433
+
434
+ subscription . unsubscribe ( ) ;
435
+ }
436
+ } ) ;
437
+ } ) ;
438
+ }
428
439
}
429
440
430
441
0 commit comments