@@ -391,42 +391,32 @@ export class _MatMenuBase
391
391
* @param origin Action from which the focus originated. Used to set the correct styling.
392
392
*/
393
393
focusFirstItem ( origin : FocusOrigin = 'program' ) : void {
394
- // When the content is rendered lazily, it takes a bit before the items are inside the DOM.
395
- if ( this . lazyContent ) {
396
- this . _ngZone . onStable . pipe ( take ( 1 ) ) . subscribe ( ( ) => this . _focusFirstItem ( origin ) ) ;
397
- } else {
398
- this . _focusFirstItem ( origin ) ;
399
- }
400
- }
401
-
402
- /**
403
- * Actual implementation that focuses the first item. Needs to be separated
404
- * out so we don't repeat the same logic in the public `focusFirstItem` method.
405
- */
406
- private _focusFirstItem ( origin : FocusOrigin ) {
407
- const manager = this . _keyManager ;
394
+ // Wait for `onStable` to ensure iOS VoiceOver screen reader focuses the first item (#24735).
395
+ this . _ngZone . onStable . pipe ( take ( 1 ) ) . subscribe ( ( ) => {
396
+ const manager = this . _keyManager ;
408
397
409
- manager . setFocusOrigin ( origin ) . setFirstItemActive ( ) ;
410
-
411
- // If there's no active item at this point, it means that all the items are disabled.
412
- // Move focus to the menu panel so keyboard events like Escape still work. Also this will
413
- // give _some_ feedback to screen readers.
414
- if ( ! manager . activeItem && this . _directDescendantItems . length ) {
415
- let element = this . _directDescendantItems . first ! . _getHostElement ( ) . parentElement ;
416
-
417
- // Because the `mat-menu` is at the DOM insertion point, not inside the overlay, we don't
418
- // have a nice way of getting a hold of the menu panel. We can't use a `ViewChild` either
419
- // because the panel is inside an `ng-template`. We work around it by starting from one of
420
- // the items and walking up the DOM.
421
- while ( element ) {
422
- if ( element . getAttribute ( 'role' ) === 'menu' ) {
423
- element . focus ( ) ;
424
- break ;
425
- } else {
426
- element = element . parentElement ;
398
+ manager . setFocusOrigin ( origin ) . setFirstItemActive ( ) ;
399
+
400
+ // If there's no active item at this point, it means that all the items are disabled.
401
+ // Move focus to the menu panel so keyboard events like Escape still work. Also this will
402
+ // give _some_ feedback to screen readers.
403
+ if ( ! manager . activeItem && this . _directDescendantItems . length ) {
404
+ let element = this . _directDescendantItems . first ! . _getHostElement ( ) . parentElement ;
405
+
406
+ // Because the `mat-menu` is at the DOM insertion point, not inside the overlay, we don't
407
+ // have a nice way of getting a hold of the menu panel. We can't use a `ViewChild` either
408
+ // because the panel is inside an `ng-template`. We work around it by starting from one of
409
+ // the items and walking up the DOM.
410
+ while ( element ) {
411
+ if ( element . getAttribute ( 'role' ) === 'menu' ) {
412
+ element . focus ( ) ;
413
+ break ;
414
+ } else {
415
+ element = element . parentElement ;
416
+ }
427
417
}
428
418
}
429
- }
419
+ } ) ;
430
420
}
431
421
432
422
/**
0 commit comments