Skip to content

Commit eef0353

Browse files
fix(material/input): Do not set aria-invalid on empty matInputs
Updates the logic for setting `aria-invalid` on `matInput` to not set the value at all if the input has no value. Prior to this PR `matInput` sets `aria-invalid="false"` for any empty `matInput`, including `required` ones. This suppresses screen readers' announcement to users that such inputs are in an invalid state. Fixes #22777
1 parent 0a4dbe1 commit eef0353

File tree

2 files changed

+5
-5
lines changed

2 files changed

+5
-5
lines changed

src/material/input/input.spec.ts

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1081,7 +1081,7 @@ describe('MatInput with forms', () => {
10811081
expect(testComponent.formControl.untouched).toBe(true, 'Expected untouched form control');
10821082
expect(containerEl.querySelectorAll('mat-error').length).toBe(0, 'Expected no error message');
10831083
expect(inputEl.getAttribute('aria-invalid'))
1084-
.toBe('false', 'Expected aria-invalid to be set to "false".');
1084+
.toBe(null, 'Expected aria-invalid not to be present.');
10851085
}));
10861086

10871087
it('should display an error message when the input is touched and invalid', fakeAsync(() => {
@@ -1135,7 +1135,7 @@ describe('MatInput with forms', () => {
11351135
expect(component.formGroup.invalid).toBe(true, 'Expected form control to be invalid');
11361136
expect(containerEl.querySelectorAll('mat-error').length).toBe(0, 'Expected no error message');
11371137
expect(inputEl.getAttribute('aria-invalid'))
1138-
.toBe('false', 'Expected aria-invalid to be set to "false".');
1138+
.toBe(null, 'Expected aria-invalid not to be present.');
11391139
expect(component.formGroupDirective.submitted)
11401140
.toBe(false, 'Expected form not to have been submitted');
11411141

@@ -1219,7 +1219,7 @@ describe('MatInput with forms', () => {
12191219
expect(describedBy).toBe(errorIds);
12201220
}));
12211221

1222-
it('should not set `aria-invalid` to true if the input is empty', fakeAsync(() => {
1222+
it('should not set `aria-invalid` if the input is empty', fakeAsync(() => {
12231223
// Submit the form since it's the one that triggers the default error state matcher.
12241224
dispatchFakeEvent(fixture.nativeElement.querySelector('form'), 'submit');
12251225
fixture.detectChanges();
@@ -1228,7 +1228,7 @@ describe('MatInput with forms', () => {
12281228
expect(testComponent.formControl.invalid).toBe(true, 'Expected form control to be invalid');
12291229
expect(inputEl.value).toBeFalsy();
12301230
expect(inputEl.getAttribute('aria-invalid'))
1231-
.toBe('false', 'Expected aria-invalid to be set to "false".');
1231+
.toBe(null, 'Expected aria-invalid not to be present.');
12321232

12331233
inputEl.value = 'not valid';
12341234
fixture.detectChanges();

src/material/input/input.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -83,7 +83,7 @@ const _MatInputBase = mixinErrorState(class {
8383
'[attr.readonly]': 'readonly && !_isNativeSelect || null',
8484
// Only mark the input as invalid for assistive technology if it has a value since the
8585
// state usually overlaps with `aria-required` when the input is empty and can be redundant.
86-
'[attr.aria-invalid]': 'errorState && !empty',
86+
'[attr.aria-invalid]': 'empty ? null : errorState',
8787
'[attr.aria-required]': 'required',
8888
},
8989
providers: [{provide: MatFormFieldControl, useExisting: MatInput}],

0 commit comments

Comments
 (0)