Skip to content

Commit b9c1825

Browse files
committed
fix(material/select): don't announce selected value multiple times
The screen reader already announces the selected value inside the select field. Therefore, pointing the `aria-labelledby` attribute to the value field made the screen reader announce the selected value multiple times. This pull request fixes this by removing the value field from `aria-labelledby`.
1 parent 9bc596f commit b9c1825

File tree

3 files changed

+15
-31
lines changed

3 files changed

+15
-31
lines changed

src/material-experimental/mdc-select/select.spec.ts

+7-12
Original file line numberDiff line numberDiff line change
@@ -192,28 +192,24 @@ describe('MDC-based MatSelect', () => {
192192
fixture.detectChanges();
193193

194194
const labelId = fixture.nativeElement.querySelector('label').id;
195-
const valueId = fixture.nativeElement.querySelector('.mat-mdc-select-value').id;
196195

197-
expect(select.getAttribute('aria-labelledby')).toBe(`${labelId} ${valueId} myLabelId`);
196+
expect(select.getAttribute('aria-labelledby')).toBe(`${labelId} myLabelId`);
198197
}));
199198

200-
it('should set aria-labelledby to the value and label IDs', fakeAsync(() => {
199+
it('should set aria-labelledby to the label IDs', fakeAsync(() => {
201200
fixture.detectChanges();
202201

203202
const labelId = fixture.nativeElement.querySelector('label').id;
204-
const valueId = fixture.nativeElement.querySelector('.mat-mdc-select-value').id;
205-
expect(select.getAttribute('aria-labelledby')).toBe(`${labelId} ${valueId}`);
203+
expect(select.getAttribute('aria-labelledby')).toBe(`${labelId}`);
206204
}));
207205

208-
it('should trim the trigger aria-labelledby when there is no label', fakeAsync(() => {
206+
it('should remove aria-labelledby when there is no label', fakeAsync(() => {
209207
fixture.componentInstance.hasLabel = false;
210208
fixture.detectChanges();
211209
flush();
212210
fixture.detectChanges();
213211

214-
// Note that we assert that there are no spaces around the value.
215-
const valueId = fixture.nativeElement.querySelector('.mat-mdc-select-value').id;
216-
expect(select.getAttribute('aria-labelledby')).toBe(`${valueId}`);
212+
expect(select.hasAttribute('aria-labelledby')).toBeFalse();
217213
}));
218214

219215
it('should set the tabindex of the select to 0 by default', fakeAsync(() => {
@@ -287,15 +283,14 @@ describe('MDC-based MatSelect', () => {
287283
expect(select.getAttribute('tabindex')).toEqual('0');
288284
}));
289285

290-
it('should set `aria-labelledby` to the value ID if there is no form field', () => {
286+
it('should remove `aria-labelledby` if there is no form field', () => {
291287
fixture.destroy();
292288

293289
const labelFixture = TestBed.createComponent(SelectWithChangeEvent);
294290
labelFixture.detectChanges();
295291
select = labelFixture.debugElement.query(By.css('mat-select'))!.nativeElement;
296-
const valueId = labelFixture.nativeElement.querySelector('.mat-mdc-select-value').id;
297292

298-
expect(select.getAttribute('aria-labelledby')?.trim()).toBe(valueId);
293+
expect(select.hasAttribute('aria-labelledby')).toBeFalse();
299294
});
300295

301296
it('should select options via the UP/DOWN arrow keys on a closed select', fakeAsync(() => {

src/material/select/select.spec.ts

+7-12
Original file line numberDiff line numberDiff line change
@@ -191,27 +191,23 @@ describe('MatSelect', () => {
191191
fixture.detectChanges();
192192

193193
const labelId = fixture.nativeElement.querySelector('.mat-form-field-label').id;
194-
const valueId = fixture.nativeElement.querySelector('.mat-select-value').id;
195194

196-
expect(select.getAttribute('aria-labelledby')).toBe(`${labelId} ${valueId} myLabelId`);
195+
expect(select.getAttribute('aria-labelledby')).toBe(`${labelId} myLabelId`);
197196
}));
198197

199-
it('should set aria-labelledby to the value and label IDs', fakeAsync(() => {
198+
it('should set aria-labelledby to the label IDs', fakeAsync(() => {
200199
fixture.detectChanges();
201200

202201
const labelId = fixture.nativeElement.querySelector('.mat-form-field-label').id;
203-
const valueId = fixture.nativeElement.querySelector('.mat-select-value').id;
204-
expect(select.getAttribute('aria-labelledby')).toBe(`${labelId} ${valueId}`);
202+
expect(select.getAttribute('aria-labelledby')).toBe(`${labelId}`);
205203
}));
206204

207-
it('should trim the trigger aria-labelledby when there is no label', fakeAsync(() => {
205+
it('should remove the aria-labelledby when there is no label', fakeAsync(() => {
208206
// Reset the `placeholder` which also controls the label of the form field.
209207
fixture.componentInstance.select.placeholder = '';
210208
fixture.detectChanges();
211209

212-
// Note that we assert that there are no spaces around the value.
213-
const valueId = fixture.nativeElement.querySelector('.mat-select-value').id;
214-
expect(select.getAttribute('aria-labelledby')).toBe(`${valueId}`);
210+
expect(select.hasAttribute('aria-labelledby')).toBeFalse();
215211
}));
216212

217213
it('should set the tabindex of the select to 0 by default', fakeAsync(() => {
@@ -285,15 +281,14 @@ describe('MatSelect', () => {
285281
expect(select.getAttribute('tabindex')).toEqual('0');
286282
}));
287283

288-
it('should set `aria-labelledby` to the value ID if there is no form field', () => {
284+
it('should remove `aria-labelledby` if there is no form field', () => {
289285
fixture.destroy();
290286

291287
const labelFixture = TestBed.createComponent(SelectWithChangeEvent);
292288
labelFixture.detectChanges();
293289
select = labelFixture.debugElement.query(By.css('mat-select'))!.nativeElement;
294-
const valueId = labelFixture.nativeElement.querySelector('.mat-select-value').id;
295290

296-
expect(select.getAttribute('aria-labelledby')?.trim()).toBe(valueId);
291+
expect(select.hasAttribute('aria-labelledby')).toBeFalse();
297292
});
298293

299294
it('should select options via the UP/DOWN arrow keys on a closed select', fakeAsync(() => {

src/material/select/select.ts

+1-7
Original file line numberDiff line numberDiff line change
@@ -1127,13 +1127,7 @@ export abstract class _MatSelectBase<C>
11271127
}
11281128

11291129
const labelId = this._parentFormField?.getLabelId();
1130-
let value = (labelId ? labelId + ' ' : '') + this._valueId;
1131-
1132-
if (this.ariaLabelledby) {
1133-
value += ' ' + this.ariaLabelledby;
1134-
}
1135-
1136-
return value;
1130+
return this.ariaLabelledby ? labelId + ' ' + this.ariaLabelledby : labelId;
11371131
}
11381132

11391133
/** Called when the overlay panel is done animating. */

0 commit comments

Comments
 (0)