From 9f0afd3f8618b2a50fe669fffbd460281b070b3f Mon Sep 17 00:00:00 2001 From: Michael Eaton Date: Mon, 24 May 2021 12:53:04 -0700 Subject: [PATCH] fix(material/input): Do not set `aria-invalid` on required empty `matInput`s 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 --- src/material-experimental/mdc-input/input.spec.ts | 4 ++-- src/material-experimental/mdc-input/input.ts | 2 +- src/material/input/input.spec.ts | 4 ++-- src/material/input/input.ts | 2 +- 4 files changed, 6 insertions(+), 6 deletions(-) diff --git a/src/material-experimental/mdc-input/input.spec.ts b/src/material-experimental/mdc-input/input.spec.ts index 4d7a47f0a18b..ac0eb7fa00ac 100644 --- a/src/material-experimental/mdc-input/input.spec.ts +++ b/src/material-experimental/mdc-input/input.spec.ts @@ -1081,7 +1081,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(); @@ -1090,7 +1090,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(); diff --git a/src/material-experimental/mdc-input/input.ts b/src/material-experimental/mdc-input/input.ts index c16577810517..329d386fc21a 100644 --- a/src/material-experimental/mdc-input/input.ts +++ b/src/material-experimental/mdc-input/input.ts @@ -39,7 +39,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}], diff --git a/src/material/input/input.spec.ts b/src/material/input/input.spec.ts index 96695bec2f98..d1c8c48a8f60 100644 --- a/src/material/input/input.spec.ts +++ b/src/material/input/input.spec.ts @@ -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(); @@ -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(); diff --git a/src/material/input/input.ts b/src/material/input/input.ts index 7a56680b6843..3443a23681d9 100644 --- a/src/material/input/input.ts +++ b/src/material/input/input.ts @@ -83,7 +83,7 @@ const _MatInputBase = mixinErrorState(class { '[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}],