Skip to content

Commit f86072d

Browse files
committed
fix(overlay): backdrop exit animation not working
Fixes the transition when closing an overlay with an opaque backdrop appearing broken. The issue comes the fact that when we start animating the backdrop out, we also remove the `backdropClass` which makes the backdrop transparent. We don't need to remove the class, because we'll remove the backdrop from the DOM and clear the reference once the transition is done.
1 parent 2e54f13 commit f86072d

File tree

1 file changed

+30
-24
lines changed

1 file changed

+30
-24
lines changed

src/cdk/overlay/overlay-ref.ts

Lines changed: 30 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -332,38 +332,44 @@ export class OverlayRef implements PortalOutlet {
332332
detachBackdrop(): void {
333333
let backdropToDetach = this._backdropElement;
334334

335-
if (backdropToDetach) {
336-
let finishDetach = () => {
337-
// It may not be attached to anything in certain cases (e.g. unit tests).
338-
if (backdropToDetach && backdropToDetach.parentNode) {
339-
backdropToDetach.parentNode.removeChild(backdropToDetach);
340-
}
335+
if (!backdropToDetach) {
336+
return;
337+
}
341338

342-
// It is possible that a new portal has been attached to this overlay since we started
343-
// removing the backdrop. If that is the case, only clear the backdrop reference if it
344-
// is still the same instance that we started to remove.
345-
if (this._backdropElement == backdropToDetach) {
346-
this._backdropElement = null;
347-
}
348-
};
339+
let finishDetach = () => {
340+
// It may not be attached to anything in certain cases (e.g. unit tests).
341+
if (backdropToDetach && backdropToDetach.parentNode) {
342+
backdropToDetach.parentNode.removeChild(backdropToDetach);
343+
}
349344

350-
backdropToDetach.classList.remove('cdk-overlay-backdrop-showing');
345+
// It is possible that a new portal has been attached to this overlay since we started
346+
// removing the backdrop. If that is the case, only clear the backdrop reference if it
347+
// is still the same instance that we started to remove.
348+
if (this._backdropElement == backdropToDetach) {
349+
this._backdropElement = null;
350+
}
351351

352352
if (this._config.backdropClass) {
353-
this._toggleClasses(backdropToDetach, this._config.backdropClass, false);
353+
this._toggleClasses(backdropToDetach!, this._config.backdropClass, false);
354354
}
355+
};
355356

356-
backdropToDetach.addEventListener('transitionend', finishDetach);
357+
backdropToDetach.classList.remove('cdk-overlay-backdrop-showing');
357358

358-
// If the backdrop doesn't have a transition, the `transitionend` event won't fire.
359-
// In this case we make it unclickable and we try to remove it after a delay.
360-
backdropToDetach.style.pointerEvents = 'none';
359+
this._ngZone.runOutsideAngular(() => {
360+
backdropToDetach!.addEventListener('transitionend', finishDetach);
361+
});
361362

362-
// Run this outside the Angular zone because there's nothing that Angular cares about.
363-
// If it were to run inside the Angular zone, every test that used Overlay would have to be
364-
// either async or fakeAsync.
365-
this._ngZone.runOutsideAngular(() => setTimeout(finishDetach, 500));
366-
}
363+
// If the backdrop doesn't have a transition, the `transitionend` event won't fire.
364+
// In this case we make it unclickable and we try to remove it after a delay.
365+
backdropToDetach.style.pointerEvents = 'none';
366+
367+
// Run this outside the Angular zone because there's nothing that Angular cares about.
368+
// If it were to run inside the Angular zone, every test that used Overlay would have to be
369+
// either async or fakeAsync.
370+
this._ngZone.runOutsideAngular(() => {
371+
setTimeout(finishDetach, 500);
372+
});
367373
}
368374

369375
/** Toggles a single CSS class or an array of classes on an element. */

0 commit comments

Comments
 (0)