Skip to content

Commit 7a63ad6

Browse files
authored
fix(cdk/overlay): ensure OverlayOutsideClickDispatcher listens to contextmenu events (#20373)
If an overlay is open and a user opens a contextmenu (on an element outside the overlay) the overlay does not close. This fix ensure that contextmenu events are treated the same way as click events which result in the outsidePointerEvents observable emitting an event.
1 parent 64145fd commit 7a63ad6

File tree

2 files changed

+34
-1
lines changed

2 files changed

+34
-1
lines changed

src/cdk/overlay/dispatchers/overlay-outside-click-dispatcher.spec.ts

+32-1
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,10 @@
11
import {TestBed, inject} from '@angular/core/testing';
22
import {Component, NgModule} from '@angular/core';
3+
import {dispatchMouseEvent} from '@angular/cdk/testing/private';
34
import {OverlayModule, OverlayContainer, Overlay} from '../index';
45
import {OverlayOutsideClickDispatcher} from './overlay-outside-click-dispatcher';
56
import {ComponentPortal} from '@angular/cdk/portal';
67

7-
88
describe('OverlayOutsideClickDispatcher', () => {
99
let outsideClickDispatcher: OverlayOutsideClickDispatcher;
1010
let overlay: Overlay;
@@ -155,6 +155,37 @@ describe('OverlayOutsideClickDispatcher', () => {
155155

156156
overlayRef.dispose();
157157
});
158+
159+
it('should dispatch an event when a context menu is triggered outside the overlay', () => {
160+
const portal = new ComponentPortal(TestComponent);
161+
const overlayRef = overlay.create();
162+
overlayRef.attach(portal);
163+
const context = document.createElement('div');
164+
document.body.appendChild(context);
165+
166+
const spy = jasmine.createSpy('overlay contextmenu spy');
167+
overlayRef.outsidePointerEvents().subscribe(spy);
168+
169+
dispatchMouseEvent(context, 'contextmenu');
170+
expect(spy).toHaveBeenCalled();
171+
172+
context.parentNode!.removeChild(context);
173+
overlayRef.dispose();
174+
});
175+
176+
it('should not dispatch an event when a context menu is triggered inside the overlay', () => {
177+
const portal = new ComponentPortal(TestComponent);
178+
const overlayRef = overlay.create();
179+
overlayRef.attach(portal);
180+
181+
const spy = jasmine.createSpy('overlay contextmenu spy');
182+
overlayRef.outsidePointerEvents().subscribe(spy);
183+
184+
dispatchMouseEvent(overlayRef.overlayElement, 'contextmenu');
185+
expect(spy).not.toHaveBeenCalled();
186+
187+
overlayRef.dispose();
188+
});
158189
});
159190

160191

src/cdk/overlay/dispatchers/overlay-outside-click-dispatcher.ts

+2
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,7 @@ export class OverlayOutsideClickDispatcher extends BaseOverlayDispatcher {
4040
// tslint:enable: max-line-length
4141
if (!this._isAttached) {
4242
this._document.body.addEventListener('click', this._clickListener, true);
43+
this._document.body.addEventListener('contextmenu', this._clickListener, true);
4344

4445
// click event is not fired on iOS. To make element "clickable" we are
4546
// setting the cursor to pointer
@@ -57,6 +58,7 @@ export class OverlayOutsideClickDispatcher extends BaseOverlayDispatcher {
5758
protected detach() {
5859
if (this._isAttached) {
5960
this._document.body.removeEventListener('click', this._clickListener, true);
61+
this._document.body.removeEventListener('contextmenu', this._clickListener, true);
6062
if (this._platform.IOS && this._cursorStyleIsSet) {
6163
this._document.body.style.cursor = this._cursorOriginalValue;
6264
this._cursorStyleIsSet = false;

0 commit comments

Comments
 (0)