diff --git a/src/lib/radio/radio.html b/src/lib/radio/radio.html
index 4c77e164b2a2..4a799f777fe3 100644
--- a/src/lib/radio/radio.html
+++ b/src/lib/radio/radio.html
@@ -18,6 +18,7 @@
[id]="inputId"
[checked]="checked"
[disabled]="disabled"
+ [tabIndex]="tabIndex"
[attr.name]="name"
[required]="required"
[attr.aria-label]="ariaLabel"
diff --git a/src/lib/radio/radio.spec.ts b/src/lib/radio/radio.spec.ts
index aa275181a417..919d6d6ddf9a 100644
--- a/src/lib/radio/radio.spec.ts
+++ b/src/lib/radio/radio.spec.ts
@@ -661,12 +661,26 @@ describe('MatRadio', () => {
let inputEl = fixture.debugElement.query(By.css('.mat-radio-input')).nativeElement;
radioButtonEl.focus();
- // Focus events don't always fire in tests, so we needc to fake it.
+ // Focus events don't always fire in tests, so we need to fake it.
dispatchFakeEvent(radioButtonEl, 'focus');
fixture.detectChanges();
expect(document.activeElement).toBe(inputEl);
});
+
+ it('should allow specifying an explicit tabindex for a single radio-button', () => {
+ const radioButtonInput = fixture.debugElement
+ .query(By.css('.mat-radio-button input')).nativeElement as HTMLInputElement;
+
+ expect(radioButtonInput.tabIndex)
+ .toBe(0, 'Expected the tabindex to be set to "0" by default.');
+
+ fixture.componentInstance.tabIndex = 4;
+ fixture.detectChanges();
+
+ expect(radioButtonInput.tabIndex)
+ .toBe(4, 'Expected the tabindex to be set to "4".');
+ });
});
describe('group interspersed with other tags', () => {
@@ -781,9 +795,11 @@ class RadioGroupWithFormControl {
}
@Component({
- template: ``
+ template: ``
})
-class FocusableRadioButton {}
+class FocusableRadioButton {
+ tabIndex: number;
+}
@Component({
template: `
diff --git a/src/lib/radio/radio.ts b/src/lib/radio/radio.ts
index f73d5b164fa0..7ed460607d26 100644
--- a/src/lib/radio/radio.ts
+++ b/src/lib/radio/radio.ts
@@ -34,10 +34,12 @@ import {
CanColor,
CanDisable,
CanDisableRipple,
+ HasTabIndex,
MatRipple,
mixinColor,
mixinDisabled,
mixinDisableRipple,
+ mixinTabIndex,
RippleConfig,
RippleRef,
} from '@angular/material/core';
@@ -315,12 +317,17 @@ export class MatRadioGroup extends _MatRadioGroupMixinBase
// Boilerplate for applying mixins to MatRadioButton.
/** @docs-private */
export class MatRadioButtonBase {
+ // Since the disabled property is manually defined for the MatRadioButton and isn't set up in
+ // the mixin base class. To be able to use the tabindex mixin, a disabled property must be
+ // defined to properly work.
+ disabled: boolean;
+
constructor(public _elementRef: ElementRef) {}
}
// As per Material design specifications the selection control radio should use the accent color
// palette by default. https://material.io/guidelines/components/selection-controls.html
export const _MatRadioButtonMixinBase =
- mixinColor(mixinDisableRipple(MatRadioButtonBase), 'accent');
+ mixinColor(mixinDisableRipple(mixinTabIndex(MatRadioButtonBase)), 'accent');
/**
* A Material design radio-button. Typically placed inside of `` elements.
@@ -330,7 +337,7 @@ export const _MatRadioButtonMixinBase =
selector: 'mat-radio-button',
templateUrl: 'radio.html',
styleUrls: ['radio.css'],
- inputs: ['color', 'disableRipple'],
+ inputs: ['color', 'disableRipple', 'tabIndex'],
encapsulation: ViewEncapsulation.None,
preserveWhitespaces: false,
exportAs: 'matRadioButton',
@@ -347,7 +354,7 @@ export const _MatRadioButtonMixinBase =
changeDetection: ChangeDetectionStrategy.OnPush,
})
export class MatRadioButton extends _MatRadioButtonMixinBase
- implements OnInit, AfterViewInit, OnDestroy, CanColor, CanDisableRipple {
+ implements OnInit, AfterViewInit, OnDestroy, CanColor, CanDisableRipple, HasTabIndex {
private _uniqueId: string = `mat-radio-${++nextUniqueId}`;