diff --git a/src/dev-app/button-toggle/button-toggle-demo.html b/src/dev-app/button-toggle/button-toggle-demo.html
index b2cfc8186f3e..474b5383790b 100644
--- a/src/dev-app/button-toggle/button-toggle-demo.html
+++ b/src/dev-app/button-toggle/button-toggle-demo.html
@@ -9,7 +9,7 @@
Exclusive Selection
-
+
format_align_left
@@ -26,7 +26,7 @@ Exclusive Selection
-
+
format_align_left
diff --git a/src/material/button-toggle/button-toggle.html b/src/material/button-toggle/button-toggle.html
index 9a2113709715..81a8b18b23c5 100644
--- a/src/material/button-toggle/button-toggle.html
+++ b/src/material/button-toggle/button-toggle.html
@@ -1,17 +1,16 @@
-
+
+
{
buttonToggleDebugElements = fixture.debugElement.queryAll(By.directive(MatButtonToggle));
buttonToggleInstances = buttonToggleDebugElements.map(debugEl => debugEl.componentInstance);
innerButtons = buttonToggleDebugElements.map(
- debugEl => debugEl.query(By.css('button'))!.nativeElement,
+ debugEl => debugEl.query(By.css('input'))!.nativeElement,
);
fixture.detectChanges();
@@ -256,7 +256,7 @@ describe('MatButtonToggle with forms', () => {
const fixture = TestBed.createComponent(ButtonToggleGroupWithIndirectDescendantToggles);
fixture.detectChanges();
- const button = fixture.nativeElement.querySelector('.mat-button-toggle button');
+ const button = fixture.nativeElement.querySelector('.mat-button-toggle input');
const groupDebugElement = fixture.debugElement.query(By.directive(MatButtonToggleGroup))!;
const groupInstance =
groupDebugElement.injector.get(MatButtonToggleGroup);
@@ -359,7 +359,7 @@ describe('MatButtonToggle without forms', () => {
buttonToggleNativeElements = buttonToggleDebugElements.map(debugEl => debugEl.nativeElement);
buttonToggleLabelElements = fixture.debugElement
- .queryAll(By.css('button'))
+ .queryAll(By.css('input'))
.map(debugEl => debugEl.nativeElement);
buttonToggleInstances = buttonToggleDebugElements.map(debugEl => debugEl.componentInstance);
@@ -401,7 +401,7 @@ describe('MatButtonToggle without forms', () => {
});
it('should disable the underlying button when the group is disabled', () => {
- const buttons = buttonToggleNativeElements.map(toggle => toggle.querySelector('button')!);
+ const buttons = buttonToggleNativeElements.map(toggle => toggle.querySelector('input')!);
expect(buttons.every(input => input.disabled)).toBe(false);
@@ -595,7 +595,7 @@ describe('MatButtonToggle without forms', () => {
buttonToggleDebugElements = fixture.debugElement.queryAll(By.directive(MatButtonToggle));
buttonToggleNativeElements = buttonToggleDebugElements.map(debugEl => debugEl.nativeElement);
buttonToggleLabelElements = fixture.debugElement
- .queryAll(By.css('button'))
+ .queryAll(By.css('input'))
.map(debugEl => debugEl.nativeElement);
buttonToggleInstances = buttonToggleDebugElements.map(debugEl => debugEl.componentInstance);
}));
@@ -612,7 +612,7 @@ describe('MatButtonToggle without forms', () => {
expect(buttonToggleInstances.every(buttonToggle => !buttonToggle.checked)).toBe(true);
const nativeCheckboxLabel = buttonToggleDebugElements[0].query(
- By.css('button'),
+ By.css('input'),
)!.nativeElement;
nativeCheckboxLabel.click();
@@ -638,7 +638,7 @@ describe('MatButtonToggle without forms', () => {
it('should check a button toggle upon interaction with underlying native checkbox', () => {
const nativeCheckboxButton = buttonToggleDebugElements[0].query(
- By.css('button'),
+ By.css('input'),
)!.nativeElement;
nativeCheckboxButton.click();
@@ -722,7 +722,7 @@ describe('MatButtonToggle without forms', () => {
)!.nativeElement;
buttonToggleInstance = buttonToggleDebugElement.componentInstance;
buttonToggleButtonElement = buttonToggleNativeElement.querySelector(
- 'button',
+ 'input',
)! as HTMLButtonElement;
}));
@@ -761,7 +761,7 @@ describe('MatButtonToggle without forms', () => {
}));
it('should focus on underlying input element when focus() is called', () => {
- const nativeButton = buttonToggleDebugElement.query(By.css('button'))!.nativeElement;
+ const nativeButton = buttonToggleDebugElement.query(By.css('input'))!.nativeElement;
expect(document.activeElement).not.toBe(nativeButton);
buttonToggleInstance.focus();
@@ -790,7 +790,7 @@ describe('MatButtonToggle without forms', () => {
const fixture = TestBed.createComponent(StandaloneButtonToggle);
const checkboxDebugElement = fixture.debugElement.query(By.directive(MatButtonToggle))!;
const checkboxNativeElement = checkboxDebugElement.nativeElement;
- const buttonElement = checkboxNativeElement.querySelector('button') as HTMLButtonElement;
+ const buttonElement = checkboxNativeElement.querySelector('input') as HTMLButtonElement;
fixture.detectChanges();
expect(buttonElement.hasAttribute('aria-label')).toBe(false);
@@ -800,7 +800,7 @@ describe('MatButtonToggle without forms', () => {
const fixture = TestBed.createComponent(ButtonToggleWithAriaLabel);
const checkboxDebugElement = fixture.debugElement.query(By.directive(MatButtonToggle))!;
const checkboxNativeElement = checkboxDebugElement.nativeElement;
- const buttonElement = checkboxNativeElement.querySelector('button') as HTMLButtonElement;
+ const buttonElement = checkboxNativeElement.querySelector('input') as HTMLButtonElement;
fixture.detectChanges();
expect(buttonElement.getAttribute('aria-label')).toBe('Super effective');
@@ -825,7 +825,7 @@ describe('MatButtonToggle without forms', () => {
const fixture = TestBed.createComponent(ButtonToggleWithAriaLabelledby);
checkboxDebugElement = fixture.debugElement.query(By.directive(MatButtonToggle))!;
checkboxNativeElement = checkboxDebugElement.nativeElement;
- buttonElement = checkboxNativeElement.querySelector('button') as HTMLButtonElement;
+ buttonElement = checkboxNativeElement.querySelector('input') as HTMLButtonElement;
fixture.detectChanges();
expect(buttonElement.getAttribute('aria-labelledby')).toBe('some-id');
@@ -835,7 +835,7 @@ describe('MatButtonToggle without forms', () => {
const fixture = TestBed.createComponent(StandaloneButtonToggle);
checkboxDebugElement = fixture.debugElement.query(By.directive(MatButtonToggle))!;
checkboxNativeElement = checkboxDebugElement.nativeElement;
- buttonElement = checkboxNativeElement.querySelector('button') as HTMLButtonElement;
+ buttonElement = checkboxNativeElement.querySelector('input') as HTMLButtonElement;
fixture.detectChanges();
expect(buttonElement.getAttribute('aria-labelledby')).toBe(null);
@@ -847,7 +847,7 @@ describe('MatButtonToggle without forms', () => {
const fixture = TestBed.createComponent(ButtonToggleWithTabindex);
fixture.detectChanges();
- const button = fixture.nativeElement.querySelector('.mat-button-toggle button');
+ const button = fixture.nativeElement.querySelector('.mat-button-toggle input');
expect(button.getAttribute('tabindex')).toBe('3');
});
@@ -866,7 +866,7 @@ describe('MatButtonToggle without forms', () => {
fixture.detectChanges();
const host = fixture.nativeElement.querySelector('.mat-button-toggle');
- const button = host.querySelector('button');
+ const button = host.querySelector('input');
expect(document.activeElement).not.toBe(button);
@@ -891,7 +891,7 @@ describe('MatButtonToggle without forms', () => {
const hostNode: HTMLElement = fixture.nativeElement.querySelector('.mat-button-toggle');
expect(hostNode.hasAttribute('name')).toBe(false);
- expect(hostNode.querySelector('button')!.getAttribute('name')).toBe('custom-name');
+ expect(hostNode.querySelector('input')!.getAttribute('name')).toBe('custom-name');
});
it(
diff --git a/src/material/button-toggle/button-toggle.ts b/src/material/button-toggle/button-toggle.ts
index b5ea5c549226..9baa8919b77d 100644
--- a/src/material/button-toggle/button-toggle.ts
+++ b/src/material/button-toggle/button-toggle.ts
@@ -106,8 +106,8 @@ export class MatButtonToggleChange {
{provide: MAT_BUTTON_TOGGLE_GROUP, useExisting: MatButtonToggleGroup},
],
host: {
- 'role': 'group',
'class': 'mat-button-toggle-group',
+ '[role]': "multiple ? 'group' : 'radiogroup'",
'[attr.aria-disabled]': 'disabled',
'[class.mat-button-toggle-vertical]': 'vertical',
'[class.mat-button-toggle-group-appearance-standard]': 'appearance === "standard"',
@@ -417,6 +417,11 @@ export class MatButtonToggle implements OnInit, AfterViewInit, OnDestroy {
*/
@Input('aria-labelledby') ariaLabelledby: string | null = null;
+ /** Type of the button toggle. Either 'radio' or 'button'. */
+ get type(): string {
+ return this._isSingleSelector() ? 'radio' : 'button';
+ }
+
/** Underlying native `button` element. */
@ViewChild('button') _buttonElement: ElementRef;
@@ -573,6 +578,15 @@ export class MatButtonToggle implements OnInit, AfterViewInit, OnDestroy {
return this.name || null;
}
+ /** Get the aria-pressed attribute value. */
+ _getAriaPressed(): boolean | null {
+ // When the toggle stands alone, or in multiple selection mode, use aria-pressed attribute.
+ if (!this._isSingleSelector()) {
+ return this.checked;
+ }
+ return null;
+ }
+
/** Whether the toggle is in single selection mode. */
private _isSingleSelector(): boolean {
return this.buttonToggleGroup && !this.buttonToggleGroup.multiple;