Skip to content

Commit ba94b3c

Browse files
committed
fix(overlay): backdrop blocking element scroll
Fixes a long-standing where the backdrop doesn't allow the user to scroll, if the main scrollable container is not the body. Fixes #6927.
1 parent a9e550e commit ba94b3c

File tree

2 files changed

+58
-2
lines changed

2 files changed

+58
-2
lines changed

src/cdk/overlay/overlay-ref.ts

+24-2
Original file line numberDiff line numberDiff line change
@@ -10,13 +10,22 @@ import {Direction, Directionality} from '@angular/cdk/bidi';
1010
import {ComponentPortal, Portal, PortalOutlet, TemplatePortal} from '@angular/cdk/portal';
1111
import {ComponentRef, EmbeddedViewRef, NgZone} from '@angular/core';
1212
import {Location} from '@angular/common';
13-
import {Observable, Subject, merge, SubscriptionLike, Subscription, Observer} from 'rxjs';
14-
import {take, takeUntil} from 'rxjs/operators';
13+
import {
14+
Observable,
15+
Subject,
16+
merge,
17+
SubscriptionLike,
18+
Subscription,
19+
Observer,
20+
fromEvent,
21+
} from 'rxjs';
22+
import {take, takeUntil, tap, debounceTime} from 'rxjs/operators';
1523
import {OverlayKeyboardDispatcher} from './keyboard/overlay-keyboard-dispatcher';
1624
import {OverlayConfig} from './overlay-config';
1725
import {coerceCssPixelValue, coerceArray} from '@angular/cdk/coercion';
1826
import {OverlayReference} from './overlay-reference';
1927
import {PositionStrategy} from './position/position-strategy';
28+
import {BlockScrollStrategy} from './scroll/block-scroll-strategy';
2029

2130

2231
/** An object where all of its properties cannot be written. */
@@ -364,6 +373,19 @@ export class OverlayRef implements PortalOutlet, OverlayReference {
364373
this._backdropElement.addEventListener('click',
365374
(event: MouseEvent) => this._backdropClick.next(event));
366375

376+
if (!(this._config.scrollStrategy instanceof BlockScrollStrategy)) {
377+
// When the user starts scrolling by mouse, disable pointer events on the backdrop. This
378+
// allows for non-body scroll containers (e.g. a sidenav container), which would normally
379+
// be blocked due to the backdrop, to scroll. When the user has stopped scrolling for 100ms
380+
// restore the pointer events in order for the click handler to work.
381+
this._ngZone.runOutsideAngular(() => {
382+
fromEvent(this._backdropElement!, 'wheel').pipe(
383+
tap(() => this._backdropElement!.style.pointerEvents = 'none'),
384+
debounceTime(100)
385+
).subscribe(() => this._backdropElement!.style.pointerEvents = '');
386+
});
387+
}
388+
367389
// Add class to fade-in the backdrop after one frame.
368390
if (typeof requestAnimationFrame !== 'undefined') {
369391
this._ngZone.runOutsideAngular(() => {

src/cdk/overlay/overlay.spec.ts

+34
Original file line numberDiff line numberDiff line change
@@ -725,6 +725,40 @@ describe('Overlay', () => {
725725
.toBeLessThan(children.indexOf(host), 'Expected backdrop to be before the host in the DOM');
726726
});
727727

728+
it('should disable pointer events on the backdrop when scrolling', fakeAsync(() => {
729+
let overlayRef = overlay.create(config);
730+
overlayRef.attach(componentPortal);
731+
732+
viewContainerFixture.detectChanges();
733+
let backdrop = overlayContainerElement.querySelector('.cdk-overlay-backdrop') as HTMLElement;
734+
735+
expect(backdrop.style.pointerEvents).toBeFalsy();
736+
737+
dispatchFakeEvent(backdrop, 'wheel');
738+
739+
expect(backdrop.style.pointerEvents).toBe('none');
740+
741+
tick(100);
742+
743+
expect(backdrop.style.pointerEvents).toBeFalsy();
744+
}));
745+
746+
it('should not disable pointer events on the backdrop when scrolling is blocked', () => {
747+
config.scrollStrategy = overlay.scrollStrategies.block();
748+
749+
let overlayRef = overlay.create(config);
750+
overlayRef.attach(componentPortal);
751+
752+
viewContainerFixture.detectChanges();
753+
let backdrop = overlayContainerElement.querySelector('.cdk-overlay-backdrop') as HTMLElement;
754+
755+
expect(backdrop.style.pointerEvents).toBeFalsy();
756+
757+
dispatchFakeEvent(backdrop, 'wheel');
758+
759+
expect(backdrop.style.pointerEvents).toBeFalsy();
760+
});
761+
728762
});
729763

730764
describe('panelClass', () => {

0 commit comments

Comments
 (0)