Missing aria-describedby on Symfony form fields causing screen reader to ignore validation errors
0 reputation · 19 Sept 2023, 11:33 UTC
0 reputation · 19 Sept 2023, 11:33 UTC
Goal: Make every invalid form field expose an aria-describedby attribute that points to the ID of its error list so that assistive technologies announce validation messages when the field gains focus.
Constraint: The default Symfony form themes (including the Bootstrap theme) do not automatically add aria-describedby linking the input to the form_errors block; developers must manually set the attribute in a custom theme or via the FormView attr array, and there is no configuration switch to enable this behavior globally.
Uncertainty: It is not documented whether the Form component could be extended with a flag or Twig helper to automatically generate the association, or if a custom form theme is the only supported way to achieve this accessibility improvement.
Questions: Is there a way to configure the Form component to automatically add aria-describedby attributes based on a field’s error state? Can the form_errors block be modified to output a predictable ID that can be referenced by aria-describedby without manual templating? Should a custom form theme be considered the recommended solution, or is a core feature missing?
34775 reputation · 19 Sept 2023, 15:30 UTC
Symfony does not provide a global flag to automatically link validation errors to inputs via ARIA. The confirmed way to achieve this is to override the field widget block in a custom Twig theme and set the attribute.
templates/form/fields.html.twig, that extends the base theme you are using (e.g., bootstrap_4_layout.html.twig).field_widget block (or the specific widget block like integer_widget) to add the attribute when the field has errors.form_errors block to render the error list with a predictable ID, such as {{ id }}_errors.config/packages/twig.yaml under form_themes.{# templates/form/fields.html.twig #}
{% use 'bootstrap_4_layout.html.twig' %}
{% block field_widget %}
{% set attr = attr|merge({ 'aria-describedby': id ~ '_errors' }) %}
{{ block('form_widget_simple') }}
{% endblock %}
{% block form_errors %}
{% if errors|length > 0 %}
{% for error in errors %}
- {{ error.message }}
{% endfor %}
{% endif %}
{% endblock %}
After clearing the cache, each invalid field will have aria-describedby pointing to the error list, and screen readers will announce the messages when the field receives focus.
Use comments to ask for clarification. Post a solution as an answer.
No question comments on this page.