|
1 |
| -import {ComponentFixture, fakeAsync, flush, inject, TestBed, tick} from '@angular/core/testing'; |
2 |
| -import {By} from '@angular/platform-browser'; |
3 |
| -import {NoopAnimationsModule} from '@angular/platform-browser/animations'; |
| 1 | +import {FocusMonitor} from '@angular/cdk/a11y'; |
| 2 | +import {Direction, Directionality} from '@angular/cdk/bidi'; |
| 3 | +import {DOWN_ARROW, END, ESCAPE, HOME, LEFT_ARROW, RIGHT_ARROW, TAB} from '@angular/cdk/keycodes'; |
| 4 | +import {Overlay, OverlayContainer} from '@angular/cdk/overlay'; |
| 5 | +import {ScrollDispatcher} from '@angular/cdk/scrolling'; |
| 6 | +import { |
| 7 | + createKeyboardEvent, |
| 8 | + createMouseEvent, |
| 9 | + dispatchEvent, |
| 10 | + dispatchFakeEvent, |
| 11 | + dispatchKeyboardEvent, |
| 12 | + dispatchMouseEvent, |
| 13 | + MockNgZone, |
| 14 | + patchElementFocus, |
| 15 | +} from '@angular/cdk/testing'; |
4 | 16 | import {
|
| 17 | + ChangeDetectionStrategy, |
5 | 18 | Component,
|
6 | 19 | ElementRef,
|
7 | 20 | EventEmitter,
|
8 | 21 | Input,
|
9 |
| - Output, |
10 | 22 | NgZone,
|
| 23 | + Output, |
| 24 | + Provider, |
| 25 | + QueryList, |
11 | 26 | TemplateRef,
|
| 27 | + Type, |
12 | 28 | ViewChild,
|
13 | 29 | ViewChildren,
|
14 |
| - QueryList, |
15 |
| - Type, |
16 |
| - Provider, |
17 | 30 | } from '@angular/core';
|
18 |
| -import {Direction, Directionality} from '@angular/cdk/bidi'; |
19 |
| -import {OverlayContainer, Overlay} from '@angular/cdk/overlay'; |
20 |
| -import {ESCAPE, LEFT_ARROW, RIGHT_ARROW, DOWN_ARROW, TAB, HOME, END} from '@angular/cdk/keycodes'; |
| 31 | +import {ComponentFixture, fakeAsync, flush, inject, TestBed, tick} from '@angular/core/testing'; |
| 32 | +import {MatRipple} from '@angular/material/core'; |
| 33 | +import {By} from '@angular/platform-browser'; |
| 34 | +import {NoopAnimationsModule} from '@angular/platform-browser/animations'; |
| 35 | +import {Subject} from 'rxjs'; |
21 | 36 | import {
|
22 | 37 | MAT_MENU_DEFAULT_OPTIONS,
|
23 | 38 | MatMenu,
|
| 39 | + MatMenuItem, |
24 | 40 | MatMenuModule,
|
25 | 41 | MatMenuPanel,
|
26 | 42 | MatMenuTrigger,
|
27 | 43 | MenuPositionX,
|
28 | 44 | MenuPositionY,
|
29 |
| - MatMenuItem, |
30 | 45 | } from './index';
|
31 |
| -import {MENU_PANEL_TOP_PADDING, MAT_MENU_SCROLL_STRATEGY} from './menu-trigger'; |
32 |
| -import {MatRipple} from '@angular/material/core'; |
33 |
| -import { |
34 |
| - dispatchKeyboardEvent, |
35 |
| - dispatchMouseEvent, |
36 |
| - dispatchEvent, |
37 |
| - createKeyboardEvent, |
38 |
| - createMouseEvent, |
39 |
| - dispatchFakeEvent, |
40 |
| - patchElementFocus, |
41 |
| - MockNgZone, |
42 |
| -} from '@angular/cdk/testing'; |
43 |
| -import {Subject} from 'rxjs'; |
44 |
| -import {ScrollDispatcher} from '@angular/cdk/scrolling'; |
45 |
| -import {FocusMonitor} from '@angular/cdk/a11y'; |
| 46 | +import {MAT_MENU_SCROLL_STRATEGY, MENU_PANEL_TOP_PADDING} from './menu-trigger'; |
46 | 47 |
|
47 | 48 |
|
48 | 49 | describe('MatMenu', () => {
|
@@ -892,6 +893,25 @@ describe('MatMenu', () => {
|
892 | 893 | expect(document.activeElement).toBe(items[1], 'Expected second item to be focused');
|
893 | 894 | flush();
|
894 | 895 | }));
|
| 896 | + |
| 897 | + it('should open submenus when the menu is inside an OnPush component', fakeAsync(() => { |
| 898 | + const fixture = createComponent(LazyMenuWithOnPush); |
| 899 | + fixture.detectChanges(); |
| 900 | + |
| 901 | + // Open the top-level menu |
| 902 | + fixture.componentInstance.rootTrigger.nativeElement.click(); |
| 903 | + fixture.detectChanges(); |
| 904 | + flush(); |
| 905 | + |
| 906 | + // Dispatch a `mouseenter` on the menu item to open the submenu. |
| 907 | + // This will only work if the top-level menu is aware the this menu item exists. |
| 908 | + dispatchMouseEvent(fixture.componentInstance.menuItemWithSubmenu.nativeElement, 'mouseenter'); |
| 909 | + fixture.detectChanges(); |
| 910 | + flush(); |
| 911 | + |
| 912 | + expect(overlayContainerElement.querySelectorAll('.mat-menu-item').length) |
| 913 | + .toBe(2, 'Expected two open menus'); |
| 914 | + })); |
895 | 915 | });
|
896 | 916 |
|
897 | 917 | describe('positions', () => {
|
@@ -2373,3 +2393,25 @@ class SimpleMenuWithRepeater {
|
2373 | 2393 | items = ['Pizza', 'Pasta'];
|
2374 | 2394 | }
|
2375 | 2395 |
|
| 2396 | +@Component({ |
| 2397 | + template: ` |
| 2398 | + <button [matMenuTriggerFor]="menu" #triggerEl>Toggle menu</button> |
| 2399 | +
|
| 2400 | + <mat-menu #menu="matMenu"> |
| 2401 | + <ng-template matMenuContent> |
| 2402 | + <button [matMenuTriggerFor]="menu2" mat-menu-item #menuItem>Item</button> |
| 2403 | + </ng-template> |
| 2404 | + </mat-menu> |
| 2405 | +
|
| 2406 | + <mat-menu #menu2="matMenu"> |
| 2407 | + <ng-template matMenuContent> |
| 2408 | + <button mat-menu-item #subMenuItem>Sub item</button> |
| 2409 | + </ng-template> |
| 2410 | + </mat-menu> |
| 2411 | + `, |
| 2412 | + changeDetection: ChangeDetectionStrategy.OnPush, |
| 2413 | +}) |
| 2414 | +class LazyMenuWithOnPush { |
| 2415 | + @ViewChild('triggerEl', {static: false, read: ElementRef}) rootTrigger: ElementRef; |
| 2416 | + @ViewChild('menuItem', {static: false, read: ElementRef}) menuItemWithSubmenu: ElementRef; |
| 2417 | +} |
0 commit comments