Skip to content

Commit

Permalink
fix(material/input): Do not set aria-invalid on required empty `mat…
Browse files Browse the repository at this point in the history
…Input`s (#22802)

Updates the logic for setting `aria-invalid` on `matInput` to not set
the attribute at all if the input is `required` and 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

(cherry picked from commit d185294)
  • Loading branch information
ByzantineFailure authored and andrewseguin committed Jun 7, 2021
1 parent 046461b commit 0bba6ea
Show file tree
Hide file tree
Showing 4 changed files with 6 additions and 6 deletions.
4 changes: 2 additions & 2 deletions src/material-experimental/mdc-input/input.spec.ts
Expand Up @@ -1070,7 +1070,7 @@ describe('MatMdcInput with forms', () => {
expect(describedBy).toBe(errorIds);
}));

it('should not set `aria-invalid` to true if the input is empty', fakeAsync(() => {
it('should set `aria-invalid` to true if the input is empty', fakeAsync(() => {
// Submit the form since it's the one that triggers the default error state matcher.
dispatchFakeEvent(fixture.nativeElement.querySelector('form'), 'submit');
fixture.detectChanges();
Expand All @@ -1079,7 +1079,7 @@ describe('MatMdcInput with forms', () => {
expect(testComponent.formControl.invalid).toBe(true, 'Expected form control to be invalid');
expect(inputEl.value).toBeFalsy();
expect(inputEl.getAttribute('aria-invalid'))
.toBe('false', 'Expected aria-invalid to be set to "false".');
.toBe('true', 'Expected aria-invalid to be set to "true"');

inputEl.value = 'not valid';
fixture.detectChanges();
Expand Down
2 changes: 1 addition & 1 deletion src/material-experimental/mdc-input/input.ts
Expand Up @@ -35,7 +35,7 @@ import {MatInput as BaseMatInput} from '@angular/material/input';
'[attr.readonly]': 'readonly && !_isNativeSelect || null',
// Only mark the input as invalid for assistive technology if it has a value since the
// state usually overlaps with `aria-required` when the input is empty and can be redundant.
'[attr.aria-invalid]': 'errorState && !empty',
'[attr.aria-invalid]': '(empty && required) ? null : errorState',
'[attr.aria-required]': 'required',
},
providers: [{provide: MatFormFieldControl, useExisting: MatInput}],
Expand Down
4 changes: 2 additions & 2 deletions src/material/input/input.spec.ts
Expand Up @@ -1219,7 +1219,7 @@ describe('MatInput with forms', () => {
expect(describedBy).toBe(errorIds);
}));

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

inputEl.value = 'not valid';
fixture.detectChanges();
Expand Down
2 changes: 1 addition & 1 deletion src/material/input/input.ts
Expand Up @@ -86,7 +86,7 @@ const _MatInputMixinBase: CanUpdateErrorStateCtor & typeof MatInputBase =
'[attr.readonly]': 'readonly && !_isNativeSelect || null',
// Only mark the input as invalid for assistive technology if it has a value since the
// state usually overlaps with `aria-required` when the input is empty and can be redundant.
'[attr.aria-invalid]': 'errorState && !empty',
'[attr.aria-invalid]': '(empty && required) ? null : errorState',
'[attr.aria-required]': 'required',
},
providers: [{provide: MatFormFieldControl, useExisting: MatInput}],
Expand Down

0 comments on commit 0bba6ea

Please sign in to comment.