@@ -391,42 +391,32 @@ export class _MatMenuBase
391391 * @param origin Action from which the focus originated. Used to set the correct styling.
392392 */
393393 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 ;
408397
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+ }
427417 }
428418 }
429- }
419+ } ) ;
430420 }
431421
432422 /**
0 commit comments