Skip to content

bug(matInput): Screen Readers do not announce that an empty matInput[required] is invalid #22777

Closed
@ByzantineFailure

Description

@ByzantineFailure

Reproduction

StackBlitz: https://components-issue-pcy3uq.stackblitz.io

Steps to reproduce:

  1. Turn on a screen reader
  2. Focus the input
  3. Move focus away from the input
  4. Return focus to the input

Expected Behavior

Screen reader announces to the user that the form field is invalid.

Actual Behavior

Screen reader does not announce to the user that the form field is invalid.

Note that while the value in mat-error is announced to the user when the field is focused there is no indication that the field itself is invalid (unless the error message itself contains that).

Environment

  • Angular:^12.0.1
  • CDK/Material: ^12.0.1
  • Browser(s): Any
  • Operating System (e.g. Windows, macOS, Ubuntu): Any

Details

This issue is rooted in the fact that matInput sets aria-invalid="false" for empty inputs. This causes screen readers not to announce that a required input is invalid despite being empty.

We should update matInput to not apply aria-invalid on instances that do not have any value within the input. This may be accomplished via changing this line within the matInput directive from:

'[attr.aria-invalid]': 'errorState && !empty'

to:

'[attr.aria-invalid]': 'empty ? null : errorState'

Doing this will allow us to comply with the ARIA spec for aria-invalid (since aria-invalid isn't applied to the element until the user has entered some data) while also providing the correct announcements (since aria-required/input[required] is indicating to the screen reader that the empty field is invalid).

Testing methodology

I used this HTML document for testing ARIA attribute behavior with VoiceOver on Chrome and JAWS on Chrome:

<html>
  <body>
    <form>
      <input required/>
      <button type="submit">Submit</button>
    </form>
  </body>
</html>

Testing with adding/removing various aria attributes on the input element showed the following behavior:

ARIA attributes value JAWS+Chrome VoiceOver+Chrome
aria-required not present, aria-invalid not present no value "Edit Required invalid entry" "required, invalid data, edit text"
aria-required not present, aria-invalid not present "value" "Edit Required, value" "value, required, edit text"
aria-required="true", aria-invalid not present no value "Edit Required, invalid entry" "required, invalid data, edit text"
aria-required="true", aria-invalid not present "value" "Edit required, value" "value, required, edit text"
aria-required="true", aria-invalid="true" no value "Edit required, invalid entry" "required, invalid data, edit text"
aria-required="true", aria-invalid="true" "value" "Edit required, invalid entry" "value, required, invalid data, edit text"
aria-required="true", aria-invalid="false" no value "Edit required, type in text" "required, edit text"
aria-required="true", aria-invalid="false" "value" "Edit required, type in text" "value, required, edit text"

While I did not test with NVDA/ChromeVox or on FF/IE/etc. I'm reasonably confident that these results will replicate across these use cases as well.

Metadata

Metadata

Assignees

No one assigned

    Labels

    AccessibilityThis issue is related to accessibility (a11y)P3An issue that is relevant to core functions, but does not impede progress. Important, but not urgentarea: material/input

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions