Skip to content

Commit 6d0032e

Browse files
authored
feat(module:dropdown): close context menu on escape (#7915)
* feat(module:dropdown): close context menu dropdown on keydown escape * refactor(module:dropdown): optimize closing context performance
1 parent baab16c commit 6d0032e

File tree

2 files changed

+32
-8
lines changed

2 files changed

+32
-8
lines changed

components/dropdown/context-menu.service.spec.ts

Lines changed: 23 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,12 @@
1+
import { ESCAPE } from '@angular/cdk/keycodes';
12
import { OverlayContainer, ScrollDispatcher } from '@angular/cdk/overlay';
23
import { ApplicationRef, Component, Provider, Type, ViewChild } from '@angular/core';
34
import { ComponentFixture, TestBed, fakeAsync, inject, tick } from '@angular/core/testing';
45
import { NoopAnimationsModule } from '@angular/platform-browser/animations';
56
import { RouterTestingModule } from '@angular/router/testing';
67
import { Subject } from 'rxjs';
78

8-
import { createMouseEvent } from 'ng-zorro-antd/core/testing';
9+
import { createKeyboardEvent, createMouseEvent, dispatchEvent } from 'ng-zorro-antd/core/testing';
910
import { NzMenuModule } from 'ng-zorro-antd/menu';
1011

1112
import { NzContextMenuService } from './context-menu.service';
@@ -120,6 +121,27 @@ describe('context-menu', () => {
120121
expect(overlayContainerElement.textContent).toBe('');
121122
}).not.toThrowError();
122123
}));
124+
it('should backdrop work with keyboard event ESCAPE', fakeAsync(() => {
125+
const fixture = createComponent(NzTestDropdownContextMenuComponent, [], []);
126+
const keyboardEvent = createKeyboardEvent('keydown', ESCAPE, undefined, 'Escape');
127+
fixture.detectChanges();
128+
expect(overlayContainerElement.textContent).toBe('');
129+
fixture.detectChanges();
130+
expect(() => {
131+
const fakeEvent = createMouseEvent('contextmenu', 300, 300);
132+
const component = fixture.componentInstance;
133+
component.nzContextMenuService.create(fakeEvent, component.nzDropdownMenuComponent);
134+
fixture.detectChanges();
135+
tick(1000);
136+
fixture.detectChanges();
137+
expect(overlayContainerElement.textContent).toContain('1st menu item');
138+
dispatchEvent(document.body, keyboardEvent);
139+
fixture.detectChanges();
140+
tick(1000);
141+
fixture.detectChanges();
142+
expect(overlayContainerElement.textContent).toBe('');
143+
}).not.toThrowError();
144+
}));
123145
it('should not run change detection if the overlay is clicked inside', async () => {
124146
const fixture = createComponent(NzTestDropdownContextMenuComponent, [], []);
125147
fixture.detectChanges();

components/dropdown/context-menu.service.ts

Lines changed: 9 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -6,8 +6,8 @@
66
import { ConnectionPositionPair, Overlay, OverlayRef } from '@angular/cdk/overlay';
77
import { TemplatePortal } from '@angular/cdk/portal';
88
import { Injectable, NgZone } from '@angular/core';
9-
import { fromEvent, Subscription } from 'rxjs';
10-
import { filter, take } from 'rxjs/operators';
9+
import { fromEvent, merge, Subscription } from 'rxjs';
10+
import { filter, first } from 'rxjs/operators';
1111

1212
import { NzContextMenuServiceModule } from './context-menu.service.module';
1313
import { NzDropdownMenuComponent } from './dropdown-menu.component';
@@ -51,13 +51,15 @@ export class NzContextMenuService {
5151

5252
this.closeSubscription.add(
5353
this.ngZone.runOutsideAngular(() =>
54-
fromEvent<MouseEvent>(document, 'click')
55-
.pipe(
54+
merge(
55+
fromEvent<MouseEvent>(document, 'click').pipe(
5656
filter(event => !!this.overlayRef && !this.overlayRef.overlayElement.contains(event.target as HTMLElement)),
5757
/** handle firefox contextmenu event **/
58-
filter(event => event.button !== 2),
59-
take(1)
60-
)
58+
filter(event => event.button !== 2)
59+
),
60+
fromEvent<KeyboardEvent>(document, 'keydown').pipe(filter(event => event.key === 'Escape'))
61+
)
62+
.pipe(first())
6163
.subscribe(() => this.ngZone.run(() => this.close()))
6264
)
6365
);

0 commit comments

Comments
 (0)