@@ -25,8 +25,8 @@ import {
25
25
OnDestroy ,
26
26
OnInit ,
27
27
Output ,
28
- QueryList ,
29
28
TemplateRef ,
29
+ QueryList ,
30
30
ViewChild ,
31
31
ViewEncapsulation ,
32
32
} from '@angular/core' ;
@@ -36,7 +36,7 @@ import {matMenuAnimations} from './menu-animations';
36
36
import { MatMenuContent } from './menu-content' ;
37
37
import { throwMatMenuInvalidPositionX , throwMatMenuInvalidPositionY } from './menu-errors' ;
38
38
import { MatMenuItem } from './menu-item' ;
39
- import { MatMenuPanel } from './menu-panel' ;
39
+ import { MAT_MENU_PANEL , MatMenuPanel } from './menu-panel' ;
40
40
import { MenuPositionX , MenuPositionY } from './menu-positions' ;
41
41
42
42
@@ -84,18 +84,27 @@ const MAT_MENU_BASE_ELEVATION = 2;
84
84
styleUrls : [ 'menu.css' ] ,
85
85
changeDetection : ChangeDetectionStrategy . OnPush ,
86
86
encapsulation : ViewEncapsulation . None ,
87
+ exportAs : 'matMenu' ,
87
88
animations : [
88
89
matMenuAnimations . transformMenu ,
89
90
matMenuAnimations . fadeInItems
90
91
] ,
91
- exportAs : 'matMenu'
92
+ providers : [
93
+ { provide : MAT_MENU_PANEL , useExisting : MatMenu }
94
+ ]
92
95
} )
93
- export class MatMenu implements OnInit , AfterContentInit , MatMenuPanel , OnDestroy {
96
+ export class MatMenu implements OnInit , AfterContentInit , MatMenuPanel < MatMenuItem > , OnDestroy {
94
97
private _keyManager : FocusKeyManager < MatMenuItem > ;
95
98
private _xPosition : MenuPositionX = this . _defaultOptions . xPosition ;
96
99
private _yPosition : MenuPositionY = this . _defaultOptions . yPosition ;
97
100
private _previousElevation : string ;
98
101
102
+ /** Menu items inside the current menu. */
103
+ private _items : MatMenuItem [ ] = [ ] ;
104
+
105
+ /** Emits whenever the amount of menu items changes. */
106
+ private _itemChanges = new Subject < MatMenuItem [ ] > ( ) ;
107
+
99
108
/** Subscription to tab events on the menu panel */
100
109
private _tabSubscription = Subscription . EMPTY ;
101
110
@@ -106,7 +115,10 @@ export class MatMenu implements OnInit, AfterContentInit, MatMenuPanel, OnDestro
106
115
_panelAnimationState : 'void' | 'enter' = 'void' ;
107
116
108
117
/** Emits whenever an animation on the menu completes. */
109
- _animationDone = new Subject < void > ( ) ;
118
+ _animationDone = new Subject < AnimationEvent > ( ) ;
119
+
120
+ /** Whether the menu is animating. */
121
+ _isAnimating : boolean ;
110
122
111
123
/** Parent menu of the current menu panel. */
112
124
parentMenu : MatMenuPanel | undefined ;
@@ -142,7 +154,11 @@ export class MatMenu implements OnInit, AfterContentInit, MatMenuPanel, OnDestro
142
154
/** @docs -private */
143
155
@ViewChild ( TemplateRef ) templateRef : TemplateRef < any > ;
144
156
145
- /** List of the items inside of a menu. */
157
+ /**
158
+ * List of the items inside of a menu.
159
+ * @deprecated
160
+ * @deletion -target 7.0.0
161
+ */
146
162
@ContentChildren ( MatMenuItem ) items : QueryList < MatMenuItem > ;
147
163
148
164
/**
@@ -218,7 +234,7 @@ export class MatMenu implements OnInit, AfterContentInit, MatMenuPanel, OnDestro
218
234
}
219
235
220
236
ngAfterContentInit ( ) {
221
- this . _keyManager = new FocusKeyManager < MatMenuItem > ( this . items ) . withWrap ( ) . withTypeAhead ( ) ;
237
+ this . _keyManager = new FocusKeyManager < MatMenuItem > ( this . _items ) . withWrap ( ) . withTypeAhead ( ) ;
222
238
this . _tabSubscription = this . _keyManager . tabOut . subscribe ( ( ) => this . close . emit ( 'tab' ) ) ;
223
239
}
224
240
@@ -229,16 +245,10 @@ export class MatMenu implements OnInit, AfterContentInit, MatMenuPanel, OnDestro
229
245
230
246
/** Stream that emits whenever the hovered menu item changes. */
231
247
_hovered ( ) : Observable < MatMenuItem > {
232
- if ( this . items ) {
233
- return this . items . changes . pipe (
234
- startWith ( this . items ) ,
235
- switchMap ( items => merge ( ...items . map ( item => item . _hovered ) ) )
236
- ) ;
237
- }
238
-
239
- return this . _ngZone . onStable
240
- . asObservable ( )
241
- . pipe ( take ( 1 ) , switchMap ( ( ) => this . _hovered ( ) ) ) ;
248
+ return this . _itemChanges . pipe (
249
+ startWith ( this . _items ) ,
250
+ switchMap ( items => merge ( ...items . map ( item => item . _hovered ) ) )
251
+ ) ;
242
252
}
243
253
244
254
/** Handle a keyboard event from the menu, delegating to the appropriate action. */
@@ -322,6 +332,35 @@ export class MatMenu implements OnInit, AfterContentInit, MatMenuPanel, OnDestro
322
332
}
323
333
}
324
334
335
+ /**
336
+ * Registers a menu item with the menu.
337
+ * @docs -private
338
+ */
339
+ addItem ( item : MatMenuItem ) {
340
+ // We register the items through this method, rather than picking them up through
341
+ // `ContentChildren`, because we need the items to be picked up by their closest
342
+ // `mat-menu` ancestor. If we used `@ContentChildren(MatMenuItem, {descendants: true})`,
343
+ // all descendant items will bleed into the top-level menu in the case where the consumer
344
+ // has `mat-menu` instances nested inside each other.
345
+ if ( this . _items . indexOf ( item ) === - 1 ) {
346
+ this . _items . push ( item ) ;
347
+ this . _itemChanges . next ( this . _items ) ;
348
+ }
349
+ }
350
+
351
+ /**
352
+ * Removes an item from the menu.
353
+ * @docs -private
354
+ */
355
+ removeItem ( item : MatMenuItem ) {
356
+ const index = this . _items . indexOf ( item ) ;
357
+
358
+ if ( this . _items . indexOf ( item ) > - 1 ) {
359
+ this . _items . splice ( index , 1 ) ;
360
+ this . _itemChanges . next ( this . _items ) ;
361
+ }
362
+ }
363
+
325
364
/** Starts the enter animation. */
326
365
_startAnimation ( ) {
327
366
// @deletion -target 7.0.0 Combine with _resetAnimation.
@@ -335,7 +374,8 @@ export class MatMenu implements OnInit, AfterContentInit, MatMenuPanel, OnDestro
335
374
}
336
375
337
376
/** Callback that is invoked when the panel animation completes. */
338
- _onAnimationDone ( ) {
339
- this . _animationDone . next ( ) ;
377
+ _onAnimationDone ( event : AnimationEvent ) {
378
+ this . _animationDone . next ( event ) ;
379
+ this . _isAnimating = false ;
340
380
}
341
381
}
0 commit comments