Skip to content

Commit 6b5100b

Browse files
crisbetotinayuangao
authored andcommitted
fix(menu): nested menu hover not working when trigger is added lazily (#6807)
Fixes not being able to open a sub-menu if its trigger is added after initialization. Fixes #6731.
1 parent cf1ece0 commit 6b5100b

File tree

2 files changed

+37
-2
lines changed

2 files changed

+37
-2
lines changed

src/lib/menu/menu-directive.ts

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,7 @@ import {ESCAPE, LEFT_ARROW, RIGHT_ARROW} from '../core/keyboard/keycodes';
3535
import {merge} from 'rxjs/observable/merge';
3636
import {Observable} from 'rxjs/Observable';
3737
import {Direction} from '@angular/cdk/bidi';
38+
import {RxChain, startWith, switchMap} from '@angular/cdk/rxjs';
3839

3940
/** Default `md-menu` options that can be overridden. */
4041
export interface MdMenuDefaultOptions {
@@ -157,7 +158,10 @@ export class MdMenu implements AfterContentInit, MdMenuPanel, OnDestroy {
157158

158159
/** Stream that emits whenever the hovered menu item changes. */
159160
hover(): Observable<MdMenuItem> {
160-
return merge(...this.items.map(item => item.hover));
161+
return RxChain.from(this.items.changes)
162+
.call(startWith, this.items)
163+
.call(switchMap, (items: MdMenuItem[]) => merge(...items.map(item => item.hover)))
164+
.result();
161165
}
162166

163167
/** Handle a keyboard event from the menu, delegating to the appropriate action. */

src/lib/menu/menu.spec.ts

Lines changed: 32 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -996,6 +996,23 @@ describe('MdMenu', () => {
996996
expect(overlay.querySelectorAll('.mat-menu-panel').length).toBe(0, 'Expected no open menus');
997997
}));
998998

999+
it('should toggle a nested menu when its trigger is added after init', fakeAsync(() => {
1000+
compileTestComponent();
1001+
instance.rootTriggerEl.nativeElement.click();
1002+
fixture.detectChanges();
1003+
expect(overlay.querySelectorAll('.mat-menu-panel').length).toBe(1, 'Expected one open menu');
1004+
1005+
instance.showLazy = true;
1006+
fixture.detectChanges();
1007+
1008+
const lazyTrigger = overlay.querySelector('#lazy-trigger')!;
1009+
1010+
dispatchMouseEvent(lazyTrigger, 'mouseenter');
1011+
fixture.detectChanges();
1012+
expect(lazyTrigger.classList)
1013+
.toContain('mat-menu-item-highlighted', 'Expected the trigger to be highlighted');
1014+
expect(overlay.querySelectorAll('.mat-menu-panel').length).toBe(2, 'Expected two open menus');
1015+
}));
9991016

10001017
});
10011018

@@ -1126,7 +1143,11 @@ class CustomMenu {
11261143
[mdMenuTriggerFor]="levelOne"
11271144
#levelOneTrigger="mdMenuTrigger">One</button>
11281145
<button md-menu-item>Two</button>
1129-
<button md-menu-item>Three</button>
1146+
<button md-menu-item
1147+
*ngIf="showLazy"
1148+
id="lazy-trigger"
1149+
[mdMenuTriggerFor]="lazy"
1150+
#lazyTrigger="mdMenuTrigger">Three</button>
11301151
</md-menu>
11311152
11321153
<md-menu #levelOne="mdMenu">
@@ -1143,6 +1164,12 @@ class CustomMenu {
11431164
<button md-menu-item>Eight</button>
11441165
<button md-menu-item>Nine</button>
11451166
</md-menu>
1167+
1168+
<md-menu #lazy="mdMenu">
1169+
<button md-menu-item>Ten</button>
1170+
<button md-menu-item>Eleven</button>
1171+
<button md-menu-item>Twelve</button>
1172+
</md-menu>
11461173
`
11471174
})
11481175
class NestedMenu {
@@ -1156,6 +1183,10 @@ class NestedMenu {
11561183

11571184
@ViewChild('levelTwo') levelTwoMenu: MdMenu;
11581185
@ViewChild('levelTwoTrigger') levelTwoTrigger: MdMenuTrigger;
1186+
1187+
@ViewChild('lazy') lazyMenu: MdMenu;
1188+
@ViewChild('lazyTrigger') lazyTrigger: MdMenuTrigger;
1189+
showLazy = false;
11591190
}
11601191

11611192
@Component({

0 commit comments

Comments
 (0)