Skip to content

Commit 37e2171

Browse files
authored
fix(datepicker): don't set aria-labelledby if form field does not have a label (#19639)
Currently we always set the `aria-labelledby` on the range inputs which will be invalid if the form field doesn't have a label. These changes add an extra check around it.
1 parent 1319c0a commit 37e2171

File tree

5 files changed

+41
-11
lines changed

5 files changed

+41
-11
lines changed

src/dev-app/datepicker/datepicker-demo.html

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -173,7 +173,8 @@ <h2>Datepicker with custom header extending the default header</h2>
173173
<h2>Range picker</h2>
174174

175175
<div class="demo-range-group">
176-
<mat-form-field appearance="legacy">
176+
<mat-form-field>
177+
<mat-label>Enter a date range</mat-label>
177178
<mat-date-range-input
178179
[formGroup]="range1"
179180
[rangePicker]="range1Picker"
@@ -183,8 +184,8 @@ <h2>Range picker</h2>
183184
[comparisonStart]="comparisonStart"
184185
[comparisonEnd]="comparisonEnd"
185186
[dateFilter]="filterOdd ? dateFilter : undefined">
186-
<input matStartDate formControlName="start"/>
187-
<input matEndDate formControlName="end"/>
187+
<input matStartDate formControlName="start" placeholder="Start date"/>
188+
<input matEndDate formControlName="end" placeholder="End date"/>
188189
</mat-date-range-input>
189190
<mat-datepicker-toggle [for]="range1Picker" matSuffix></mat-datepicker-toggle>
190191
<mat-date-range-picker

src/material/datepicker/date-range-input-parts.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -55,8 +55,8 @@ export interface MatDateRangeInputParent<D> {
5555
_startInput: MatDateRangeInputPartBase<D>;
5656
_endInput: MatDateRangeInputPartBase<D>;
5757
_groupDisabled: boolean;
58-
_handleChildValueChange: () => void;
59-
_openDatepicker: () => void;
58+
_handleChildValueChange(): void;
59+
_openDatepicker(): void;
6060
}
6161

6262
/**

src/material/datepicker/date-range-input.spec.ts

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -178,6 +178,15 @@ describe('MatDateRangeInput', () => {
178178
expect(rangeInput.getAttribute('aria-describedby')).toBe(labelId);
179179
});
180180

181+
it('should not set aria-labelledby if the form field does not have a label', () => {
182+
const fixture = createComponent(RangePickerNoLabel);
183+
fixture.detectChanges();
184+
const {start, end} = fixture.componentInstance;
185+
186+
expect(start.nativeElement.getAttribute('aria-labelledby')).toBeFalsy();
187+
expect(end.nativeElement.getAttribute('aria-labelledby')).toBeFalsy();
188+
});
189+
181190
it('should float the form field label when either input is focused', () => {
182191
const fixture = createComponent(StandardRangePicker);
183192
fixture.detectChanges();
@@ -606,6 +615,7 @@ class StandardRangePicker {
606615
})
607616
class RangePickerNoStart {}
608617

618+
609619
@Component({
610620
template: `
611621
<mat-form-field>
@@ -637,3 +647,20 @@ class RangePickerNgModel {
637647
end: Date | null = null;
638648
}
639649

650+
651+
@Component({
652+
template: `
653+
<mat-form-field>
654+
<mat-date-range-input [rangePicker]="rangePicker">
655+
<input #start matStartDate/>
656+
<input #end matEndDate/>
657+
</mat-date-range-input>
658+
659+
<mat-date-range-picker #rangePicker></mat-date-range-picker>
660+
</mat-form-field>
661+
`
662+
})
663+
class RangePickerNoLabel {
664+
@ViewChild('start') start: ElementRef<HTMLInputElement>;
665+
@ViewChild('end') end: ElementRef<HTMLInputElement>;
666+
}

src/material/datepicker/date-range-input.ts

Lines changed: 7 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -49,7 +49,7 @@ let nextUniqueId = 0;
4949
'[class.mat-date-range-input-hide-placeholders]': '_shouldHidePlaceholders()',
5050
'[attr.id]': 'null',
5151
'role': 'group',
52-
'[attr.aria-labelledby]': '_ariaLabelledBy',
52+
'[attr.aria-labelledby]': '_getAriaLabelledby()',
5353
'[attr.aria-describedby]': '_ariaDescribedBy',
5454
},
5555
changeDetection: ChangeDetectionStrategy.OnPush,
@@ -177,9 +177,6 @@ export class MatDateRangeInput<D> implements MatFormFieldControl<DateRange<D>>,
177177
/** Value for the `aria-describedby` attribute of the inputs. */
178178
_ariaDescribedBy: string | null = null;
179179

180-
/** Value for the `aria-labelledby` attribute of the inputs. */
181-
_ariaLabelledBy: string | null = null;
182-
183180
/** Date selection model currently registered with the input. */
184181
private _model: MatDateSelectionModel<DateRange<D>> | undefined;
185182

@@ -218,7 +215,6 @@ export class MatDateRangeInput<D> implements MatFormFieldControl<DateRange<D>>,
218215

219216
// TODO(crisbeto): remove `as any` after #18206 lands.
220217
this.ngControl = control as any;
221-
this._ariaLabelledBy = _formField ? _formField._labelId : null;
222218
}
223219

224220
/**
@@ -311,6 +307,12 @@ export class MatDateRangeInput<D> implements MatFormFieldControl<DateRange<D>>,
311307
return (!this._formField || this._formField._hideControlPlaceholder()) && this.empty;
312308
}
313309

310+
/** Gets the value for the `aria-labelledby` attribute of the inputs. */
311+
_getAriaLabelledby() {
312+
const formField = this._formField;
313+
return formField && formField._hasFloatingLabel() ? formField._labelId : null;
314+
}
315+
314316
/**
315317
* @param obj The object to check.
316318
* @returns The given object if it is both a date instance and valid, otherwise null.

tools/public_api_guard/material/datepicker.d.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -287,7 +287,6 @@ export declare class MatDatepickerToggleIcon {
287287

288288
export declare class MatDateRangeInput<D> implements MatFormFieldControl<DateRange<D>>, MatDatepickerControl<D>, MatDateRangeInputParent<D>, AfterContentInit, OnDestroy {
289289
_ariaDescribedBy: string | null;
290-
_ariaLabelledBy: string | null;
291290
_disabledChange: Subject<boolean>;
292291
_endInput: MatEndDate<D>;
293292
_groupDisabled: boolean;
@@ -318,6 +317,7 @@ export declare class MatDateRangeInput<D> implements MatFormFieldControl<DateRan
318317
stateChanges: Subject<void>;
319318
get value(): DateRange<D> | null;
320319
constructor(_changeDetectorRef: ChangeDetectorRef, _elementRef: ElementRef<HTMLElement>, control: ControlContainer, _dateAdapter: DateAdapter<D>, _formField?: MatFormField | undefined);
320+
_getAriaLabelledby(): string | null;
321321
_getInputMirrorValue(): string;
322322
_handleChildValueChange(): void;
323323
_openDatepicker(): void;

0 commit comments

Comments
 (0)