Skip to content

Commit

Permalink
fix(radio): take default tabindex value from attribute (#20453)
Browse files Browse the repository at this point in the history
This is something that we have everywhere where we deal with `tabindex`, but it was missing on the radio button. Adds some logic that will take the initial `tabindex` value from the attribute through DI.

(cherry picked from commit 2c83b40)
  • Loading branch information
crisbeto authored and wagnermaciel committed Sep 16, 2020
1 parent 60a3527 commit 1f4d598
Show file tree
Hide file tree
Showing 5 changed files with 45 additions and 11 deletions.
12 changes: 11 additions & 1 deletion src/material-experimental/mdc-radio/radio.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -794,6 +794,16 @@ describe('MDC-based MatRadio', () => {
expect(radioButtonEl.getAttribute('tabindex')).toBe('-1');
});

it('should forward a pre-defined tabindex to the underlying input', () => {
const predefinedFixture = TestBed.createComponent(RadioButtonWithPredefinedTabindex);
predefinedFixture.detectChanges();

const radioButtonInput = predefinedFixture.debugElement
.query(By.css('.mat-mdc-radio-button input'))!.nativeElement as HTMLInputElement;

expect(radioButtonInput.getAttribute('tabindex')).toBe('5');
});

it('should remove the aria attributes from the host element', () => {
const predefinedFixture = TestBed.createComponent(RadioButtonWithPredefinedAriaAttributes);
predefinedFixture.detectChanges();
Expand Down Expand Up @@ -1016,7 +1026,7 @@ class TranscludingWrapper {}


@Component({
template: `<mat-radio-button tabindex="0"></mat-radio-button>`
template: `<mat-radio-button tabindex="5"></mat-radio-button>`
})
class RadioButtonWithPredefinedTabindex {}

Expand Down
6 changes: 4 additions & 2 deletions src/material-experimental/mdc-radio/radio.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@

import {
AfterViewInit,
Attribute,
ChangeDetectionStrategy,
ChangeDetectorRef,
Component,
Expand Down Expand Up @@ -136,9 +137,10 @@ export class MatRadioButton extends _MatRadioButtonBase implements AfterViewInit
_radioDispatcher: UniqueSelectionDispatcher,
@Optional() @Inject(ANIMATION_MODULE_TYPE) _animationMode?: string,
@Optional() @Inject(MAT_RADIO_DEFAULT_OPTIONS)
_providerOverride?: MatRadioDefaultOptions) {
_providerOverride?: MatRadioDefaultOptions,
@Attribute('tabindex') tabIndex?: string) {
super(radioGroup, elementRef, _changeDetector, _focusMonitor,
_radioDispatcher, _animationMode, _providerOverride);
_radioDispatcher, _animationMode, _providerOverride, tabIndex);
}

ngAfterViewInit() {
Expand Down
12 changes: 11 additions & 1 deletion src/material/radio/radio.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -787,6 +787,16 @@ describe('MatRadio', () => {
expect(radioButtonEl.getAttribute('tabindex')).toBe('-1');
});

it('should forward a pre-defined tabindex to the underlying input', () => {
const predefinedFixture = TestBed.createComponent(RadioButtonWithPredefinedTabindex);
predefinedFixture.detectChanges();

const radioButtonInput = predefinedFixture.debugElement
.query(By.css('.mat-radio-button input'))!.nativeElement as HTMLInputElement;

expect(radioButtonInput.getAttribute('tabindex')).toBe('5');
});

it('should remove the aria attributes from the host element', () => {
const predefinedFixture = TestBed.createComponent(RadioButtonWithPredefinedAriaAttributes);
predefinedFixture.detectChanges();
Expand Down Expand Up @@ -999,7 +1009,7 @@ class TranscludingWrapper {}


@Component({
template: `<mat-radio-button tabindex="0"></mat-radio-button>`
template: `<mat-radio-button tabindex="5"></mat-radio-button>`
})
class RadioButtonWithPredefinedTabindex {}

Expand Down
20 changes: 16 additions & 4 deletions src/material/radio/radio.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,11 +7,17 @@
*/

import {FocusMonitor} from '@angular/cdk/a11y';
import {BooleanInput, coerceBooleanProperty, NumberInput} from '@angular/cdk/coercion';
import {
BooleanInput,
coerceBooleanProperty,
coerceNumberProperty,
NumberInput,
} from '@angular/cdk/coercion';
import {UniqueSelectionDispatcher} from '@angular/cdk/collections';
import {
AfterContentInit,
AfterViewInit,
Attribute,
ChangeDetectionStrategy,
ChangeDetectorRef,
Component,
Expand Down Expand Up @@ -489,13 +495,18 @@ export abstract class _MatRadioButtonBase extends _MatRadioButtonMixinBase imple
private _focusMonitor: FocusMonitor,
private _radioDispatcher: UniqueSelectionDispatcher,
public _animationMode?: string,
private _providerOverride?: MatRadioDefaultOptions) {
private _providerOverride?: MatRadioDefaultOptions,
tabIndex?: string) {
super(elementRef);

// Assertions. Ideally these should be stripped out by the compiler.
// TODO(jelbourn): Assert that there's no name binding AND a parent radio group.
this.radioGroup = radioGroup;

if (tabIndex) {
this.tabIndex = coerceNumberProperty(tabIndex, 0);
}

this._removeUniqueSelectionListener =
_radioDispatcher.listen((id: string, name: string) => {
if (id !== this.id && name === this.name) {
Expand Down Expand Up @@ -641,8 +652,9 @@ export class MatRadioButton extends _MatRadioButtonBase {
radioDispatcher: UniqueSelectionDispatcher,
@Optional() @Inject(ANIMATION_MODULE_TYPE) animationMode?: string,
@Optional() @Inject(MAT_RADIO_DEFAULT_OPTIONS)
providerOverride?: MatRadioDefaultOptions) {
providerOverride?: MatRadioDefaultOptions,
@Attribute('tabindex') tabIndex?: string) {
super(radioGroup, elementRef, changeDetector, focusMonitor, radioDispatcher,
animationMode, providerOverride);
animationMode, providerOverride, tabIndex);
}
}
6 changes: 3 additions & 3 deletions tools/public_api_guard/material/radio.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ export declare abstract class _MatRadioButtonBase extends _MatRadioButtonMixinBa
set required(value: boolean);
get value(): any;
set value(value: any);
constructor(radioGroup: _MatRadioGroupBase<_MatRadioButtonBase>, elementRef: ElementRef, _changeDetector: ChangeDetectorRef, _focusMonitor: FocusMonitor, _radioDispatcher: UniqueSelectionDispatcher, _animationMode?: string | undefined, _providerOverride?: MatRadioDefaultOptions | undefined);
constructor(radioGroup: _MatRadioGroupBase<_MatRadioButtonBase>, elementRef: ElementRef, _changeDetector: ChangeDetectorRef, _focusMonitor: FocusMonitor, _radioDispatcher: UniqueSelectionDispatcher, _animationMode?: string | undefined, _providerOverride?: MatRadioDefaultOptions | undefined, tabIndex?: string);
_isRippleDisabled(): boolean;
_markForCheck(): void;
_onInputChange(event: Event): void;
Expand Down Expand Up @@ -84,9 +84,9 @@ export declare const MAT_RADIO_GROUP: InjectionToken<_MatRadioGroupBase<_MatRadi
export declare const MAT_RADIO_GROUP_CONTROL_VALUE_ACCESSOR: any;

export declare class MatRadioButton extends _MatRadioButtonBase {
constructor(radioGroup: MatRadioGroup, elementRef: ElementRef, changeDetector: ChangeDetectorRef, focusMonitor: FocusMonitor, radioDispatcher: UniqueSelectionDispatcher, animationMode?: string, providerOverride?: MatRadioDefaultOptions);
constructor(radioGroup: MatRadioGroup, elementRef: ElementRef, changeDetector: ChangeDetectorRef, focusMonitor: FocusMonitor, radioDispatcher: UniqueSelectionDispatcher, animationMode?: string, providerOverride?: MatRadioDefaultOptions, tabIndex?: string);
static ɵcmp: i0.ɵɵComponentDefWithMeta<MatRadioButton, "mat-radio-button", ["matRadioButton"], { "disableRipple": "disableRipple"; "tabIndex": "tabIndex"; }, {}, never, ["*"]>;
static ɵfac: i0.ɵɵFactoryDef<MatRadioButton, [{ optional: true; }, null, null, null, null, { optional: true; }, { optional: true; }]>;
static ɵfac: i0.ɵɵFactoryDef<MatRadioButton, [{ optional: true; }, null, null, null, null, { optional: true; }, { optional: true; }, { attribute: "tabindex"; }]>;
}

export declare class MatRadioChange {
Expand Down

0 comments on commit 1f4d598

Please sign in to comment.