@@ -40,7 +40,7 @@ import {
40
40
OnInit ,
41
41
} from '@angular/core' ;
42
42
import { merge , Observable , Subject , Subscription } from 'rxjs' ;
43
- import { startWith , switchMap , take } from 'rxjs/operators' ;
43
+ import { startWith , switchMap , take , debounceTime } from 'rxjs/operators' ;
44
44
import { matMenuAnimations } from './menu-animations' ;
45
45
import { MatMenuContent } from './menu-content' ;
46
46
import { throwMatMenuInvalidPositionX , throwMatMenuInvalidPositionY } from './menu-errors' ;
@@ -259,11 +259,34 @@ export class MatMenu implements AfterContentInit, MatMenuPanel<MatMenuItem>, OnI
259
259
ngAfterContentInit ( ) {
260
260
this . _keyManager = new FocusKeyManager < MatMenuItem > ( this . _items ) . withWrap ( ) . withTypeAhead ( ) ;
261
261
this . _tabSubscription = this . _keyManager . tabOut . subscribe ( ( ) => this . closed . emit ( 'tab' ) ) ;
262
+
263
+ // TODO(crisbeto): the `debounce` here should be removed since it's something
264
+ // that people have to flush in their tests. It'll be possible once we switch back
265
+ // to using a QueryList in #11720.
266
+ this . _ngZone . runOutsideAngular ( ( ) => {
267
+ // Move focus to another item, if the active item is removed from the list.
268
+ // We need to debounce the callback, because multiple items might be removed
269
+ // in quick succession.
270
+ this . _itemChanges . pipe ( debounceTime ( 50 ) ) . subscribe ( items => {
271
+ const manager = this . _keyManager ;
272
+
273
+ if ( manager . activeItem && items . indexOf ( manager . activeItem ) === - 1 ) {
274
+ const index = Math . max ( 0 , Math . min ( items . length - 1 , manager . activeItemIndex || 0 ) ) ;
275
+
276
+ if ( items [ index ] && ! items [ index ] . disabled ) {
277
+ manager . setActiveItem ( index ) ;
278
+ } else {
279
+ manager . setNextItemActive ( ) ;
280
+ }
281
+ }
282
+ } ) ;
283
+ } ) ;
262
284
}
263
285
264
286
ngOnDestroy ( ) {
265
287
this . _tabSubscription . unsubscribe ( ) ;
266
288
this . closed . complete ( ) ;
289
+ this . _itemChanges . complete ( ) ;
267
290
}
268
291
269
292
/** Stream that emits whenever the hovered menu item changes. */
@@ -374,7 +397,7 @@ export class MatMenu implements AfterContentInit, MatMenuPanel<MatMenuItem>, OnI
374
397
removeItem ( item : MatMenuItem ) {
375
398
const index = this . _items . indexOf ( item ) ;
376
399
377
- if ( this . _items . indexOf ( item ) > - 1 ) {
400
+ if ( index > - 1 ) {
378
401
this . _items . splice ( index , 1 ) ;
379
402
this . _itemChanges . next ( this . _items ) ;
380
403
}
0 commit comments