Skip to content

Commit 96897f8

Browse files
committed
fixup! WIP: attempt to use MutationObserver to detach overlay
1 parent 12f678c commit 96897f8

File tree

1 file changed

+24
-14
lines changed

1 file changed

+24
-14
lines changed

src/cdk/overlay/overlay-ref.ts

Lines changed: 24 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -44,6 +44,8 @@ export class OverlayRef implements PortalOutlet {
4444
private _scrollStrategy: ScrollStrategy | undefined;
4545
private _locationChanges: SubscriptionLike = Subscription.EMPTY;
4646
private _backdropRef: BackdropRef | null = null;
47+
private _detachContentMutationObserver: MutationObserver | undefined;
48+
private _detachContentAfterRenderRef: AfterRenderRef | undefined;
4749

4850
/**
4951
* Reference to the parent of the `_host` at the time it was detached. Used to restore
@@ -163,7 +165,7 @@ export class OverlayRef implements PortalOutlet {
163165

164166
// Only emit the `attachments` event once all other setup is done.
165167
this._attachments.next();
166-
this._detachWhenEmptyMutationObserver?.disconnect();
168+
this._completeDetachContent();
167169

168170
// Track this overlay by the keyboard dispatcher
169171
this._keyboardDispatcher.add(this);
@@ -224,7 +226,7 @@ export class OverlayRef implements PortalOutlet {
224226

225227
// Only emit after everything is detached.
226228
this._detachments.next();
227-
this._detachWhenEmptyMutationObserver?.disconnect();
229+
this._completeDetachContent();
228230

229231
// Remove this overlay from keyboard dispatcher tracking.
230232
this._keyboardDispatcher.remove(this);
@@ -264,7 +266,7 @@ export class OverlayRef implements PortalOutlet {
264266
}
265267

266268
this._detachments.complete();
267-
this._detachWhenEmptyMutationObserver?.disconnect();
269+
this._completeDetachContent();
268270
}
269271

270272
/** Whether the overlay has attached content. */
@@ -470,7 +472,20 @@ export class OverlayRef implements PortalOutlet {
470472
}
471473
}
472474

473-
private _detachWhenEmptyMutationObserver: MutationObserver | null = null;
475+
/** Detaches the overlay once the content finishes animating and is removed from the DOM. */
476+
private _detachContentWhenEmpty() {
477+
// Attempt to detach on the next render.
478+
this._detachContentAfterRenderRef = afterNextRender(() => this._detachContent(), {
479+
injector: this._injector,
480+
});
481+
// Otherwise wait until the content finishes animating out and detach.
482+
if (globalThis.MutationObserver && this._pane) {
483+
this._detachContentMutationObserver ||= new globalThis.MutationObserver(() => {
484+
this._detachContent();
485+
});
486+
this._detachContentMutationObserver.observe(this._pane, {childList: true});
487+
}
488+
}
474489

475490
private _detachContent() {
476491
// Needs a couple of checks for the pane and host, because
@@ -485,19 +500,14 @@ export class OverlayRef implements PortalOutlet {
485500
this._host.remove();
486501
}
487502

488-
this._detachWhenEmptyMutationObserver?.disconnect();
503+
this._completeDetachContent();
489504
}
490505
}
491506

492-
/** Detaches the overlay content next time the zone stabilizes. */
493-
private _detachContentWhenEmpty() {
494-
if (globalThis.MutationObserver && this._pane) {
495-
this._detachWhenEmptyMutationObserver ||= new globalThis.MutationObserver(() => {
496-
this._detachContent();
497-
});
498-
this._detachWhenEmptyMutationObserver.observe(this._pane, {childList: true});
499-
}
500-
this._detachContent();
507+
private _completeDetachContent() {
508+
this._detachContentAfterRenderRef?.destroy();
509+
this._detachContentAfterRenderRef = undefined;
510+
this._detachContentMutationObserver?.disconnect();
501511
}
502512

503513
/** Disposes of a scroll strategy. */

0 commit comments

Comments
 (0)