66 * found in the LICENSE file at https://angular.io/license
77 */
88
9+ import { FocusMonitor , FocusOrigin } from '@angular/cdk/a11y' ;
10+ import { UniqueSelectionDispatcher } from '@angular/cdk/collections' ;
911import {
12+ ANIMATION_MODULE_TYPE ,
1013 AfterContentInit ,
1114 AfterViewInit ,
1215 Attribute ,
13- booleanAttribute ,
1416 ChangeDetectionStrategy ,
1517 ChangeDetectorRef ,
1618 Component ,
@@ -19,24 +21,25 @@ import {
1921 DoCheck ,
2022 ElementRef ,
2123 EventEmitter ,
22- forwardRef ,
2324 Inject ,
2425 InjectionToken ,
26+ Injector ,
2527 Input ,
26- numberAttribute ,
2728 OnDestroy ,
2829 OnInit ,
2930 Optional ,
3031 Output ,
3132 QueryList ,
3233 ViewChild ,
3334 ViewEncapsulation ,
34- ANIMATION_MODULE_TYPE ,
35+ afterNextRender ,
36+ booleanAttribute ,
37+ forwardRef ,
38+ inject ,
39+ numberAttribute ,
3540} from '@angular/core' ;
36- import { _MatInternalFormField , MatRipple , ThemePalette } from '@angular/material/core' ;
37- import { FocusMonitor , FocusOrigin } from '@angular/cdk/a11y' ;
38- import { UniqueSelectionDispatcher } from '@angular/cdk/collections' ;
3941import { ControlValueAccessor , NG_VALUE_ACCESSOR } from '@angular/forms' ;
42+ import { MatRipple , ThemePalette , _MatInternalFormField } from '@angular/material/core' ;
4043import { Subscription } from 'rxjs' ;
4144
4245// Increasing integer for generating unique ids for radio components.
@@ -532,6 +535,8 @@ export class MatRadioButton implements OnInit, AfterViewInit, DoCheck, OnDestroy
532535 /** Whether animations are disabled. */
533536 _noopAnimations : boolean ;
534537
538+ private _injector = inject ( Injector ) ;
539+
535540 constructor (
536541 @Optional ( ) @Inject ( MAT_RADIO_GROUP ) radioGroup : MatRadioGroup ,
537542 protected _elementRef : ElementRef ,
@@ -695,6 +700,31 @@ export class MatRadioButton implements OnInit, AfterViewInit, DoCheck, OnDestroy
695700 if ( input ) {
696701 input . setAttribute ( 'tabindex' , value + '' ) ;
697702 this . _previousTabIndex = value ;
703+ // Wait for any pending tabindex changes to be applied
704+ afterNextRender (
705+ ( ) => {
706+ queueMicrotask ( ( ) => {
707+ // The radio group uses a "selection follows focus" pattern for tab management, so if this
708+ // radio button is currently focused and another radio button in the group becomes
709+ // selected, we should move focus to the newly selected radio button to maintain
710+ // consistency between the focused and selected states.
711+ if (
712+ group &&
713+ group . selected &&
714+ group . selected !== this &&
715+ document . activeElement === input
716+ ) {
717+ group . selected ?. _inputElement . nativeElement . focus ( ) ;
718+ // If this radio button still has focus, the selected one must be disabled. In this
719+ // case the radio group as a whole should lose focus.
720+ if ( document . activeElement === input ) {
721+ this . _inputElement . nativeElement . blur ( ) ;
722+ }
723+ }
724+ } ) ;
725+ } ,
726+ { injector : this . _injector } ,
727+ ) ;
698728 }
699729 }
700730 }
0 commit comments