@@ -31,7 +31,7 @@ import {
31
31
OnInit ,
32
32
} from '@angular/core' ;
33
33
import { merge , Observable , Subject , Subscription } from 'rxjs' ;
34
- import { startWith , switchMap , take } from 'rxjs/operators' ;
34
+ import { startWith , switchMap , take , debounceTime } from 'rxjs/operators' ;
35
35
import { matMenuAnimations } from './menu-animations' ;
36
36
import { MatMenuContent } from './menu-content' ;
37
37
import { throwMatMenuInvalidPositionX , throwMatMenuInvalidPositionY } from './menu-errors' ;
@@ -240,11 +240,34 @@ export class MatMenu implements AfterContentInit, MatMenuPanel<MatMenuItem>, OnI
240
240
ngAfterContentInit ( ) {
241
241
this . _keyManager = new FocusKeyManager < MatMenuItem > ( this . _items ) . withWrap ( ) . withTypeAhead ( ) ;
242
242
this . _tabSubscription = this . _keyManager . tabOut . subscribe ( ( ) => this . closed . emit ( 'tab' ) ) ;
243
+
244
+ // TODO(crisbeto): the `debounce` here should be removed since it's something
245
+ // that people have to flush in their tests. It'll be possible once we switch back
246
+ // to using a QueryList in #11720.
247
+ this . _ngZone . runOutsideAngular ( ( ) => {
248
+ // Move focus to another item, if the active item is removed from the list.
249
+ // We need to debounce the callback, because multiple items might be removed
250
+ // in quick succession.
251
+ this . _itemChanges . pipe ( debounceTime ( 50 ) ) . subscribe ( items => {
252
+ const manager = this . _keyManager ;
253
+
254
+ if ( manager . activeItem && items . indexOf ( manager . activeItem ) === - 1 ) {
255
+ const index = Math . max ( 0 , Math . min ( items . length - 1 , manager . activeItemIndex || 0 ) ) ;
256
+
257
+ if ( items [ index ] && ! items [ index ] . disabled ) {
258
+ manager . setActiveItem ( index ) ;
259
+ } else {
260
+ manager . setNextItemActive ( ) ;
261
+ }
262
+ }
263
+ } ) ;
264
+ } ) ;
243
265
}
244
266
245
267
ngOnDestroy ( ) {
246
268
this . _tabSubscription . unsubscribe ( ) ;
247
269
this . closed . complete ( ) ;
270
+ this . _itemChanges . complete ( ) ;
248
271
}
249
272
250
273
/** Stream that emits whenever the hovered menu item changes. */
@@ -347,7 +370,7 @@ export class MatMenu implements AfterContentInit, MatMenuPanel<MatMenuItem>, OnI
347
370
removeItem ( item : MatMenuItem ) {
348
371
const index = this . _items . indexOf ( item ) ;
349
372
350
- if ( this . _items . indexOf ( item ) > - 1 ) {
373
+ if ( index > - 1 ) {
351
374
this . _items . splice ( index , 1 ) ;
352
375
this . _itemChanges . next ( this . _items ) ;
353
376
}
0 commit comments