Skip to content

Commit 3fa399b

Browse files
andy9775wagnermaciel
authored andcommitted
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. (cherry picked from commit 7a63ad6)
1 parent 49c78ad commit 3fa399b

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

Lines changed: 32 additions & 1 deletion
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;
@@ -147,6 +147,37 @@ describe('OverlayOutsideClickDispatcher', () => {
147147
buttonShouldNotDetach.parentNode!.removeChild(buttonShouldNotDetach);
148148
overlayRef.dispose();
149149
});
150+
151+
it('should dispatch an event when a context menu is triggered outside the overlay', () => {
152+
const portal = new ComponentPortal(TestComponent);
153+
const overlayRef = overlay.create();
154+
overlayRef.attach(portal);
155+
const context = document.createElement('div');
156+
document.body.appendChild(context);
157+
158+
const spy = jasmine.createSpy('overlay contextmenu spy');
159+
overlayRef.outsidePointerEvents().subscribe(spy);
160+
161+
dispatchMouseEvent(context, 'contextmenu');
162+
expect(spy).toHaveBeenCalled();
163+
164+
context.parentNode!.removeChild(context);
165+
overlayRef.dispose();
166+
});
167+
168+
it('should not dispatch an event when a context menu is triggered inside the overlay', () => {
169+
const portal = new ComponentPortal(TestComponent);
170+
const overlayRef = overlay.create();
171+
overlayRef.attach(portal);
172+
173+
const spy = jasmine.createSpy('overlay contextmenu spy');
174+
overlayRef.outsidePointerEvents().subscribe(spy);
175+
176+
dispatchMouseEvent(overlayRef.overlayElement, 'contextmenu');
177+
expect(spy).not.toHaveBeenCalled();
178+
179+
overlayRef.dispose();
180+
});
150181
});
151182

152183

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

Lines changed: 2 additions & 0 deletions
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)