diff --git a/src/lib/menu/menu-directive.ts b/src/lib/menu/menu-directive.ts index 4dc9d57f469c..adfa8565bfac 100644 --- a/src/lib/menu/menu-directive.ts +++ b/src/lib/menu/menu-directive.ts @@ -35,6 +35,7 @@ import {ESCAPE, LEFT_ARROW, RIGHT_ARROW} from '../core/keyboard/keycodes'; import {merge} from 'rxjs/observable/merge'; import {Observable} from 'rxjs/Observable'; import {Direction} from '@angular/cdk/bidi'; +import {RxChain, startWith, switchMap} from '@angular/cdk/rxjs'; /** Default `md-menu` options that can be overridden. */ export interface MdMenuDefaultOptions { @@ -157,7 +158,10 @@ export class MdMenu implements AfterContentInit, MdMenuPanel, OnDestroy { /** Stream that emits whenever the hovered menu item changes. */ hover(): Observable { - return merge(...this.items.map(item => item.hover)); + return RxChain.from(this.items.changes) + .call(startWith, this.items) + .call(switchMap, (items: MdMenuItem[]) => merge(...items.map(item => item.hover))) + .result(); } /** Handle a keyboard event from the menu, delegating to the appropriate action. */ diff --git a/src/lib/menu/menu.spec.ts b/src/lib/menu/menu.spec.ts index 7b77a6940f44..6006dcab4f6b 100644 --- a/src/lib/menu/menu.spec.ts +++ b/src/lib/menu/menu.spec.ts @@ -996,6 +996,23 @@ describe('MdMenu', () => { expect(overlay.querySelectorAll('.mat-menu-panel').length).toBe(0, 'Expected no open menus'); })); + it('should toggle a nested menu when its trigger is added after init', fakeAsync(() => { + compileTestComponent(); + instance.rootTriggerEl.nativeElement.click(); + fixture.detectChanges(); + expect(overlay.querySelectorAll('.mat-menu-panel').length).toBe(1, 'Expected one open menu'); + + instance.showLazy = true; + fixture.detectChanges(); + + const lazyTrigger = overlay.querySelector('#lazy-trigger')!; + + dispatchMouseEvent(lazyTrigger, 'mouseenter'); + fixture.detectChanges(); + expect(lazyTrigger.classList) + .toContain('mat-menu-item-highlighted', 'Expected the trigger to be highlighted'); + expect(overlay.querySelectorAll('.mat-menu-panel').length).toBe(2, 'Expected two open menus'); + })); }); @@ -1126,7 +1143,11 @@ class CustomMenu { [mdMenuTriggerFor]="levelOne" #levelOneTrigger="mdMenuTrigger">One - + @@ -1143,6 +1164,12 @@ class CustomMenu { + + + + + + ` }) class NestedMenu { @@ -1156,6 +1183,10 @@ class NestedMenu { @ViewChild('levelTwo') levelTwoMenu: MdMenu; @ViewChild('levelTwoTrigger') levelTwoTrigger: MdMenuTrigger; + + @ViewChild('lazy') lazyMenu: MdMenu; + @ViewChild('lazyTrigger') lazyTrigger: MdMenuTrigger; + showLazy = false; } @Component({