@@ -18,12 +18,12 @@ import {
1818import { Directionality } from '@angular/cdk/bidi' ;
1919import { FocusKeyManager , FocusOrigin } from '@angular/cdk/a11y' ;
2020import { LEFT_ARROW , RIGHT_ARROW , UP_ARROW , DOWN_ARROW , ESCAPE , TAB } from '@angular/cdk/keycodes' ;
21+ import { takeUntil , mergeAll , mapTo , startWith , mergeMap , switchMap } from 'rxjs/operators' ;
22+ import { Subject , merge } from 'rxjs' ;
2123import { CdkMenuGroup } from './menu-group' ;
2224import { CDK_MENU , Menu } from './menu-interface' ;
2325import { CdkMenuItem } from './menu-item' ;
2426import { MenuStack , MenuStackItem , FocusNext } from './menu-stack' ;
25- import { Subject } from 'rxjs' ;
26- import { takeUntil } from 'rxjs/operators' ;
2727
2828/**
2929 * Directive applied to an element which configures it as a MenuBar by setting the appropriate
@@ -64,6 +64,9 @@ export class CdkMenuBar extends CdkMenuGroup implements Menu, AfterContentInit,
6464 @ContentChildren ( CdkMenuItem , { descendants : true } )
6565 private readonly _allItems : QueryList < CdkMenuItem > ;
6666
67+ /** The Menu Item which triggered the open submenu. */
68+ private _openItem ?: CdkMenuItem ;
69+
6770 constructor ( readonly _menuStack : MenuStack , @Optional ( ) private readonly _dir ?: Directionality ) {
6871 super ( ) ;
6972 }
@@ -72,6 +75,7 @@ export class CdkMenuBar extends CdkMenuGroup implements Menu, AfterContentInit,
7275 super . ngAfterContentInit ( ) ;
7376
7477 this . _setKeyManager ( ) ;
78+ this . _subscribeToMenuOpen ( ) ;
7579 this . _subscribeToMenuStack ( ) ;
7680 }
7781
@@ -163,12 +167,13 @@ export class CdkMenuBar extends CdkMenuGroup implements Menu, AfterContentInit,
163167 * Close the open menu if the current active item opened the requested MenuStackItem.
164168 * @param item the MenuStackItem requested to be closed.
165169 */
166- private _closeOpenMenu ( item : MenuStackItem ) {
170+ private _closeOpenMenu ( menu : MenuStackItem ) {
171+ const trigger = this . _openItem ;
167172 const keyManager = this . _keyManager ;
168- if ( item === keyManager . activeItem ?. getMenu ( ) ) {
169- keyManager . activeItem . getMenuTrigger ( ) ?. closeMenu ( ) ;
173+ if ( menu === trigger ?. getMenuTrigger ( ) ?. getMenu ( ) ) {
174+ trigger . getMenuTrigger ( ) ?. closeMenu ( ) ;
170175 keyManager . setFocusOrigin ( 'keyboard' ) ;
171- keyManager . setActiveItem ( keyManager . activeItem ) ;
176+ keyManager . setActiveItem ( trigger ) ;
172177 }
173178 }
174179
@@ -207,6 +212,30 @@ export class CdkMenuBar extends CdkMenuGroup implements Menu, AfterContentInit,
207212 return this . orientation === 'horizontal' ;
208213 }
209214
215+ /**
216+ * Subscribe to the menu trigger's open events in order to track the trigger which opened the menu
217+ * and stop tracking it when the menu is closed.
218+ */
219+ private _subscribeToMenuOpen ( ) {
220+ const exitCondition = merge ( this . _allItems . changes , this . _destroyed ) ;
221+ this . _allItems . changes
222+ . pipe (
223+ startWith ( this . _allItems ) ,
224+ mergeMap ( ( list : QueryList < CdkMenuItem > ) =>
225+ list
226+ . filter ( item => item . hasMenu ( ) )
227+ . map ( item => item . getMenuTrigger ( ) ! . opened . pipe ( mapTo ( item ) , takeUntil ( exitCondition ) ) )
228+ ) ,
229+ mergeAll ( ) ,
230+ switchMap ( ( item : CdkMenuItem ) => {
231+ this . _openItem = item ;
232+ return item . getMenuTrigger ( ) ! . closed ;
233+ } ) ,
234+ takeUntil ( this . _destroyed )
235+ )
236+ . subscribe ( ( ) => ( this . _openItem = undefined ) ) ;
237+ }
238+
210239 ngOnDestroy ( ) {
211240 super . ngOnDestroy ( ) ;
212241 this . _destroyed . next ( ) ;
0 commit comments