6
6
* found in the LICENSE file at https://angular.io/license
7
7
*/
8
8
9
+ import { FocusMonitor , FocusOrigin } from '@angular/cdk/a11y' ;
10
+ import { UniqueSelectionDispatcher } from '@angular/cdk/collections' ;
9
11
import {
12
+ ANIMATION_MODULE_TYPE ,
10
13
AfterContentInit ,
11
14
AfterViewInit ,
12
15
Attribute ,
13
- booleanAttribute ,
14
16
ChangeDetectionStrategy ,
15
17
ChangeDetectorRef ,
16
18
Component ,
@@ -19,24 +21,25 @@ import {
19
21
DoCheck ,
20
22
ElementRef ,
21
23
EventEmitter ,
22
- forwardRef ,
23
24
Inject ,
24
25
InjectionToken ,
26
+ Injector ,
25
27
Input ,
26
- numberAttribute ,
27
28
OnDestroy ,
28
29
OnInit ,
29
30
Optional ,
30
31
Output ,
31
32
QueryList ,
32
33
ViewChild ,
33
34
ViewEncapsulation ,
34
- ANIMATION_MODULE_TYPE ,
35
+ afterNextRender ,
36
+ booleanAttribute ,
37
+ forwardRef ,
38
+ inject ,
39
+ numberAttribute ,
35
40
} 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' ;
39
41
import { ControlValueAccessor , NG_VALUE_ACCESSOR } from '@angular/forms' ;
42
+ import { MatRipple , ThemePalette , _MatInternalFormField } from '@angular/material/core' ;
40
43
import { Subscription } from 'rxjs' ;
41
44
42
45
// Increasing integer for generating unique ids for radio components.
@@ -532,6 +535,8 @@ export class MatRadioButton implements OnInit, AfterViewInit, DoCheck, OnDestroy
532
535
/** Whether animations are disabled. */
533
536
_noopAnimations : boolean ;
534
537
538
+ private _injector = inject ( Injector ) ;
539
+
535
540
constructor (
536
541
@Optional ( ) @Inject ( MAT_RADIO_GROUP ) radioGroup : MatRadioGroup ,
537
542
protected _elementRef : ElementRef ,
@@ -695,6 +700,31 @@ export class MatRadioButton implements OnInit, AfterViewInit, DoCheck, OnDestroy
695
700
if ( input ) {
696
701
input . setAttribute ( 'tabindex' , value + '' ) ;
697
702
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
+ ) ;
698
728
}
699
729
}
700
730
}
0 commit comments