Skip to content

Commit 6b553ec

Browse files
authored
feat(material/slide-toggle): add aria-describedby input (#23104)
Similarly to other input-based components, these changes add an `aria-describedby` input to the slide toggle. Fixes #23094.
1 parent ad06d7d commit 6b553ec

File tree

7 files changed

+38
-1
lines changed

7 files changed

+38
-1
lines changed

src/material-experimental/mdc-slide-toggle/slide-toggle.html

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@
2020
[attr.aria-checked]="checked.toString()"
2121
[attr.aria-label]="ariaLabel"
2222
[attr.aria-labelledby]="ariaLabelledby"
23+
[attr.aria-describedby]="ariaDescribedby"
2324
(change)="_onChangeEvent($event)"
2425
(click)="_onInputClick($event)">
2526
</div>

src/material-experimental/mdc-slide-toggle/slide-toggle.spec.ts

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -238,6 +238,18 @@ describe('MDC-based MatSlideToggle without forms', () => {
238238
expect(inputElement.hasAttribute('aria-labelledby')).toBeFalsy();
239239
});
240240

241+
it('should forward the aria-describedby attribute to the input', () => {
242+
testComponent.slideAriaDescribedBy = 'some-element';
243+
fixture.detectChanges();
244+
245+
expect(inputElement.getAttribute('aria-describedby')).toBe('some-element');
246+
247+
testComponent.slideAriaDescribedBy = null;
248+
fixture.detectChanges();
249+
250+
expect(inputElement.hasAttribute('aria-describedby')).toBe(false);
251+
});
252+
241253
it('should set the `for` attribute to the id of the input element', () => {
242254
expect(labelElement.getAttribute('for')).toBeTruthy();
243255
expect(inputElement.getAttribute('id')).toBeTruthy();
@@ -810,6 +822,7 @@ describe('MDC-based MatSlideToggle with forms', () => {
810822
[name]="slideName"
811823
[aria-label]="slideLabel"
812824
[aria-labelledby]="slideLabelledBy"
825+
[aria-describedby]="slideAriaDescribedBy"
813826
[tabIndex]="slideTabindex"
814827
[labelPosition]="labelPosition"
815828
[disableRipple]="disableRipple"
@@ -830,6 +843,7 @@ class SlideToggleBasic {
830843
slideName: string | null;
831844
slideLabel: string | null;
832845
slideLabelledBy: string | null;
846+
slideAriaDescribedBy: string | null;
833847
slideTabindex: number;
834848
lastEvent: MatSlideToggleChange;
835849
labelPosition: string;

src/material-experimental/mdc-slide-toggle/slide-toggle.ts

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -148,6 +148,9 @@ export class MatSlideToggle implements ControlValueAccessor, AfterViewInit, OnDe
148148
/** Used to set the aria-labelledby attribute on the underlying input element. */
149149
@Input('aria-labelledby') ariaLabelledby: string | null = null;
150150

151+
/** Used to set the aria-describedby attribute on the underlying input element. */
152+
@Input('aria-describedby') ariaDescribedby: string;
153+
151154
/** Whether the slide-toggle is required. */
152155
@Input()
153156
get required(): boolean { return this._required; }

src/material/slide-toggle/slide-toggle.html

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@
1313
[attr.aria-checked]="checked.toString()"
1414
[attr.aria-label]="ariaLabel"
1515
[attr.aria-labelledby]="ariaLabelledby"
16+
[attr.aria-describedby]="ariaDescribedby"
1617
(change)="_onChangeEvent($event)"
1718
(click)="_onInputClick($event)">
1819

src/material/slide-toggle/slide-toggle.spec.ts

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -252,6 +252,18 @@ describe('MatSlideToggle without forms', () => {
252252
expect(inputElement.hasAttribute('aria-labelledby')).toBeFalsy();
253253
});
254254

255+
it('should forward the aria-describedby attribute to the input', () => {
256+
testComponent.slideAriaDescribedBy = 'some-element';
257+
fixture.detectChanges();
258+
259+
expect(inputElement.getAttribute('aria-describedby')).toBe('some-element');
260+
261+
testComponent.slideAriaDescribedBy = null;
262+
fixture.detectChanges();
263+
264+
expect(inputElement.hasAttribute('aria-describedby')).toBe(false);
265+
});
266+
255267
it('should set the `for` attribute to the id of the input element', () => {
256268
expect(labelElement.getAttribute('for')).toBeTruthy();
257269
expect(inputElement.getAttribute('id')).toBeTruthy();
@@ -886,6 +898,7 @@ describe('MatSlideToggle with forms', () => {
886898
[name]="slideName"
887899
[aria-label]="slideLabel"
888900
[aria-labelledby]="slideLabelledBy"
901+
[aria-describedby]="slideAriaDescribedBy"
889902
[tabIndex]="slideTabindex"
890903
[labelPosition]="labelPosition"
891904
[disableRipple]="disableRipple"
@@ -906,6 +919,7 @@ class SlideToggleBasic {
906919
slideName: string | null;
907920
slideLabel: string | null;
908921
slideLabelledBy: string | null;
922+
slideAriaDescribedBy: string | null;
909923
slideTabindex: number;
910924
lastEvent: MatSlideToggleChange;
911925
labelPosition: string;

src/material/slide-toggle/slide-toggle.ts

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -127,6 +127,9 @@ export class MatSlideToggle extends _MatSlideToggleBase implements OnDestroy, Af
127127
/** Used to set the aria-labelledby attribute on the underlying input element. */
128128
@Input('aria-labelledby') ariaLabelledby: string | null = null;
129129

130+
/** Used to set the aria-describedby attribute on the underlying input element. */
131+
@Input('aria-describedby') ariaDescribedby: string;
132+
130133
/** Whether the slide-toggle is required. */
131134
@Input()
132135
get required(): boolean { return this._required; }

tools/public_api_guard/material/slide-toggle.d.ts

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@ export declare class MatSlideToggle extends _MatSlideToggleBase implements OnDes
1515
_noopAnimations: boolean;
1616
_thumbBarEl: ElementRef;
1717
_thumbEl: ElementRef;
18+
ariaDescribedby: string;
1819
ariaLabel: string | null;
1920
ariaLabelledby: string | null;
2021
readonly change: EventEmitter<MatSlideToggleChange>;
@@ -45,7 +46,7 @@ export declare class MatSlideToggle extends _MatSlideToggleBase implements OnDes
4546
static ngAcceptInputType_disabled: BooleanInput;
4647
static ngAcceptInputType_required: BooleanInput;
4748
static ngAcceptInputType_tabIndex: NumberInput;
48-
static ɵcmp: i0.ɵɵComponentDeclaration<MatSlideToggle, "mat-slide-toggle", ["matSlideToggle"], { "disabled": "disabled"; "disableRipple": "disableRipple"; "color": "color"; "tabIndex": "tabIndex"; "name": "name"; "id": "id"; "labelPosition": "labelPosition"; "ariaLabel": "aria-label"; "ariaLabelledby": "aria-labelledby"; "required": "required"; "checked": "checked"; }, { "change": "change"; "toggleChange": "toggleChange"; }, never, ["*"]>;
49+
static ɵcmp: i0.ɵɵComponentDeclaration<MatSlideToggle, "mat-slide-toggle", ["matSlideToggle"], { "disabled": "disabled"; "disableRipple": "disableRipple"; "color": "color"; "tabIndex": "tabIndex"; "name": "name"; "id": "id"; "labelPosition": "labelPosition"; "ariaLabel": "aria-label"; "ariaLabelledby": "aria-labelledby"; "ariaDescribedby": "aria-describedby"; "required": "required"; "checked": "checked"; }, { "change": "change"; "toggleChange": "toggleChange"; }, never, ["*"]>;
4950
static ɵfac: i0.ɵɵFactoryDeclaration<MatSlideToggle, [null, null, null, { attribute: "tabindex"; }, null, { optional: true; }]>;
5051
}
5152

0 commit comments

Comments
 (0)