mirror of
https://github.com/angular/angular.git
synced 2026-09-14 13:54:52 +08:00
fix(overlay): disable pointer events if overlay is detached (#2747)
Fixes #2739
This commit is contained in:
@@ -29,16 +29,25 @@ describe('Overlay directives', () => {
|
||||
fixture.detectChanges();
|
||||
});
|
||||
|
||||
/** Returns the current open overlay pane element. */
|
||||
function getPaneElement() {
|
||||
return overlayContainerElement.querySelector('.cdk-overlay-pane') as HTMLElement;
|
||||
}
|
||||
|
||||
it(`should attach the overlay based on the open property`, () => {
|
||||
fixture.componentInstance.isOpen = true;
|
||||
fixture.detectChanges();
|
||||
|
||||
expect(overlayContainerElement.textContent).toContain('Menu content');
|
||||
expect(getPaneElement().style.pointerEvents)
|
||||
.toBeFalsy('Expected the overlay pane to enable pointerEvents when attached.');
|
||||
|
||||
fixture.componentInstance.isOpen = false;
|
||||
fixture.detectChanges();
|
||||
|
||||
expect(overlayContainerElement.textContent).toBe('');
|
||||
expect(getPaneElement().style.pointerEvents)
|
||||
.toBe('none', 'Expected the overlay pane to disable pointerEvents when detached.');
|
||||
});
|
||||
|
||||
it('should destroy the overlay when the directive is destroyed', () => {
|
||||
@@ -47,6 +56,8 @@ describe('Overlay directives', () => {
|
||||
fixture.destroy();
|
||||
|
||||
expect(overlayContainerElement.textContent.trim()).toBe('');
|
||||
expect(getPaneElement())
|
||||
.toBeFalsy('Expected the overlay pane element to be removed when disposed.');
|
||||
});
|
||||
|
||||
it('should use a connected position strategy with a default set of positions', () => {
|
||||
|
||||
@@ -35,10 +35,15 @@ export class OverlayRef implements PortalHost {
|
||||
}
|
||||
|
||||
let attachResult = this._portalHost.attach(portal);
|
||||
|
||||
// Update the pane element with the given state configuration.
|
||||
this.updateSize();
|
||||
this.updateDirection();
|
||||
this.updatePosition();
|
||||
|
||||
// Enable pointer events for the overlay pane element.
|
||||
this._togglePointerEvents(true);
|
||||
|
||||
return attachResult;
|
||||
}
|
||||
|
||||
@@ -48,6 +53,12 @@ export class OverlayRef implements PortalHost {
|
||||
*/
|
||||
detach(): Promise<any> {
|
||||
this._detachBackdrop();
|
||||
|
||||
// When the overlay is detached, the pane element should disable pointer events.
|
||||
// This is necessary because otherwise the pane element will cover the page and disable
|
||||
// pointer events therefore. Depends on the position strategy and the applied pane boundaries.
|
||||
this._togglePointerEvents(false);
|
||||
|
||||
return this._portalHost.detach();
|
||||
}
|
||||
|
||||
@@ -115,6 +126,11 @@ export class OverlayRef implements PortalHost {
|
||||
}
|
||||
}
|
||||
|
||||
/** Toggles the pointer events for the overlay pane element. */
|
||||
private _togglePointerEvents(enablePointer: boolean) {
|
||||
this._pane.style.pointerEvents = enablePointer ? null : 'none';
|
||||
}
|
||||
|
||||
/** Attaches a backdrop for this overlay. */
|
||||
private _attachBackdrop() {
|
||||
this._backdropElement = document.createElement('div');
|
||||
|
||||
@@ -62,6 +62,23 @@ describe('Overlay', () => {
|
||||
expect(overlayContainerElement.textContent).toBe('');
|
||||
});
|
||||
|
||||
it('should disable pointer events of the pane element if detached', () => {
|
||||
let overlayRef = overlay.create();
|
||||
let paneElement = overlayRef.overlayElement;
|
||||
|
||||
overlayRef.attach(componentPortal);
|
||||
|
||||
expect(paneElement.childNodes.length).not.toBe(0);
|
||||
expect(paneElement.style.pointerEvents)
|
||||
.toBeFalsy('Expected the overlay pane to enable pointerEvents when attached.');
|
||||
|
||||
overlayRef.detach();
|
||||
|
||||
expect(paneElement.childNodes.length).toBe(0);
|
||||
expect(paneElement.style.pointerEvents)
|
||||
.toBe('none', 'Expected the overlay pane to disable pointerEvents when detached.');
|
||||
});
|
||||
|
||||
it('should open multiple overlays', () => {
|
||||
let pizzaOverlayRef = overlay.create();
|
||||
pizzaOverlayRef.attach(componentPortal);
|
||||
|
||||
@@ -65,11 +65,14 @@ export class DomPortalHost extends BasePortalHost {
|
||||
let viewContainer = portal.viewContainerRef;
|
||||
let viewRef = viewContainer.createEmbeddedView(portal.templateRef);
|
||||
|
||||
// The method `createEmbeddedView` will add the view as a child of the viewContainer.
|
||||
// But for the DomPortalHost the view can be added everywhere in the DOM (e.g Overlay Container)
|
||||
// To move the view to the specified host element. We just re-append the existing root nodes.
|
||||
viewRef.rootNodes.forEach(rootNode => this._hostDomElement.appendChild(rootNode));
|
||||
|
||||
this.setDisposeFn((() => {
|
||||
let index = viewContainer.indexOf(viewRef);
|
||||
if (index != -1) {
|
||||
if (index !== -1) {
|
||||
viewContainer.remove(index);
|
||||
}
|
||||
}));
|
||||
|
||||
Reference in New Issue
Block a user