@@ -18,12 +18,12 @@ import {
18
18
import { Directionality } from '@angular/cdk/bidi' ;
19
19
import { FocusKeyManager , FocusOrigin } from '@angular/cdk/a11y' ;
20
20
import { 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' ;
21
23
import { CdkMenuGroup } from './menu-group' ;
22
24
import { CDK_MENU , Menu } from './menu-interface' ;
23
25
import { CdkMenuItem } from './menu-item' ;
24
26
import { MenuStack , MenuStackItem , FocusNext } from './menu-stack' ;
25
- import { Subject } from 'rxjs' ;
26
- import { takeUntil } from 'rxjs/operators' ;
27
27
28
28
/**
29
29
* 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,
64
64
@ContentChildren ( CdkMenuItem , { descendants : true } )
65
65
private readonly _allItems : QueryList < CdkMenuItem > ;
66
66
67
+ /** The Menu Item which triggered the open submenu. */
68
+ private _openItem ?: CdkMenuItem ;
69
+
67
70
constructor ( readonly _menuStack : MenuStack , @Optional ( ) private readonly _dir ?: Directionality ) {
68
71
super ( ) ;
69
72
}
@@ -72,6 +75,7 @@ export class CdkMenuBar extends CdkMenuGroup implements Menu, AfterContentInit,
72
75
super . ngAfterContentInit ( ) ;
73
76
74
77
this . _setKeyManager ( ) ;
78
+ this . _subscribeToMenuOpen ( ) ;
75
79
this . _subscribeToMenuStack ( ) ;
76
80
}
77
81
@@ -163,12 +167,13 @@ export class CdkMenuBar extends CdkMenuGroup implements Menu, AfterContentInit,
163
167
* Close the open menu if the current active item opened the requested MenuStackItem.
164
168
* @param item the MenuStackItem requested to be closed.
165
169
*/
166
- private _closeOpenMenu ( item : MenuStackItem ) {
170
+ private _closeOpenMenu ( menu : MenuStackItem ) {
171
+ const trigger = this . _openItem ;
167
172
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 ( ) ;
170
175
keyManager . setFocusOrigin ( 'keyboard' ) ;
171
- keyManager . setActiveItem ( keyManager . activeItem ) ;
176
+ keyManager . setActiveItem ( trigger ) ;
172
177
}
173
178
}
174
179
@@ -207,6 +212,30 @@ export class CdkMenuBar extends CdkMenuGroup implements Menu, AfterContentInit,
207
212
return this . orientation === 'horizontal' ;
208
213
}
209
214
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
+
210
239
ngOnDestroy ( ) {
211
240
super . ngOnDestroy ( ) ;
212
241
this . _destroyed . next ( ) ;
0 commit comments