From 6089a3ee0b5d172fef61bbb364fa8cb9c844f3a1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jean-Fran=C3=A7ois=20Morin-Abdullah?= Date: Mon, 23 Jun 2025 15:27:17 +0200 Subject: [PATCH 1/2] [TwigBridgeRessources] add aria-invalid and aria-describedby on form inputs when validation failure exist --- .../bootstrap_3_horizontal_layout.html.twig | 8 ++----- .../views/Form/bootstrap_3_layout.html.twig | 10 +++----- .../bootstrap_4_horizontal_layout.html.twig | 8 +++++-- .../views/Form/bootstrap_4_layout.html.twig | 8 +++++-- .../bootstrap_5_horizontal_layout.html.twig | 8 ++----- .../views/Form/bootstrap_5_layout.html.twig | 10 ++++---- .../views/Form/form_div_layout.html.twig | 23 +++++++++++++++---- .../views/Form/form_table_layout.html.twig | 8 ++----- .../views/Form/foundation_5_layout.html.twig | 10 +++----- .../views/Form/tailwind_2_layout.html.twig | 2 +- 10 files changed, 48 insertions(+), 47 deletions(-) diff --git a/src/Symfony/Bridge/Twig/Resources/views/Form/bootstrap_3_horizontal_layout.html.twig b/src/Symfony/Bridge/Twig/Resources/views/Form/bootstrap_3_horizontal_layout.html.twig index 49cd804398b5e..04ab90defadba 100644 --- a/src/Symfony/Bridge/Twig/Resources/views/Form/bootstrap_3_horizontal_layout.html.twig +++ b/src/Symfony/Bridge/Twig/Resources/views/Form/bootstrap_3_horizontal_layout.html.twig @@ -22,11 +22,7 @@ col-sm-2 {# Rows #} -{% block form_row -%} - {%- set widget_attr = {} -%} - {%- if help is not empty -%} - {%- set widget_attr = {attr: {'aria-describedby': id ~"_help"}} -%} - {%- endif -%} +{% block form_row_render -%} {{- form_label(form) -}}
@@ -35,7 +31,7 @@ col-sm-2 {{- form_errors(form) -}}
{##} -{%- endblock form_row %} +{%- endblock form_row_render -%} {% block submit_row -%} {#--#} diff --git a/src/Symfony/Bridge/Twig/Resources/views/Form/bootstrap_3_layout.html.twig b/src/Symfony/Bridge/Twig/Resources/views/Form/bootstrap_3_layout.html.twig index f4e313b4756c8..3102e2e7086a5 100644 --- a/src/Symfony/Bridge/Twig/Resources/views/Form/bootstrap_3_layout.html.twig +++ b/src/Symfony/Bridge/Twig/Resources/views/Form/bootstrap_3_layout.html.twig @@ -127,18 +127,14 @@ {# Rows #} -{% block form_row -%} - {%- set widget_attr = {} -%} - {%- if help is not empty -%} - {%- set widget_attr = {attr: {'aria-describedby': id ~"_help"}} -%} - {%- endif -%} +{% block form_row_render -%} {{- form_label(form) }} {# -#} {{ form_widget(form, widget_attr) }} {# -#} {{- form_help(form) -}} {{ form_errors(form) }} {# -#} {# -#} -{%- endblock form_row %} +{%- endblock form_row_render -%} {% block button_row -%} @@ -187,7 +183,7 @@ {% block form_errors -%} {% if errors|length > 0 -%} {% if form is not rootform %}{% else %}
{% endif %} -
    +
      {%- for error in errors -%}
    • {{ error.message }}
    • {%- endfor -%} diff --git a/src/Symfony/Bridge/Twig/Resources/views/Form/bootstrap_4_horizontal_layout.html.twig b/src/Symfony/Bridge/Twig/Resources/views/Form/bootstrap_4_horizontal_layout.html.twig index 990b324cb0d17..5a029a80fc1e6 100644 --- a/src/Symfony/Bridge/Twig/Resources/views/Form/bootstrap_4_horizontal_layout.html.twig +++ b/src/Symfony/Bridge/Twig/Resources/views/Form/bootstrap_4_horizontal_layout.html.twig @@ -24,10 +24,14 @@ col-sm-2 {%- if expanded is defined and expanded -%} {{ block('fieldset_form_row') }} {%- else -%} - {%- set widget_attr = {} -%} + {%- set attr = {} -%} {%- if help is not empty -%} - {%- set widget_attr = {attr: {'aria-describedby': id ~"_help"}} -%} + {%- set attr = attr|merge({'aria-describedby': id ~"_help"}) -%} + {%- endif -%} + {%- if errors|length > 0 -%} + {%- set attr = attr|merge({'aria-invalid': 'true'}) -%} {%- endif -%} + {%- set widget_attr = {attr: attr} -%} {{- form_label(form) -}}
      diff --git a/src/Symfony/Bridge/Twig/Resources/views/Form/bootstrap_4_layout.html.twig b/src/Symfony/Bridge/Twig/Resources/views/Form/bootstrap_4_layout.html.twig index 458cc6847ed8e..f1a99423e0718 100644 --- a/src/Symfony/Bridge/Twig/Resources/views/Form/bootstrap_4_layout.html.twig +++ b/src/Symfony/Bridge/Twig/Resources/views/Form/bootstrap_4_layout.html.twig @@ -282,10 +282,14 @@ {%- if compound is defined and compound -%} {%- set element = 'fieldset' -%} {%- endif -%} - {%- set widget_attr = {} -%} + {%- set attr = {} -%} {%- if help is not empty -%} - {%- set widget_attr = {attr: {'aria-describedby': id ~"_help"}} -%} + {%- set attr = attr|merge({'aria-describedby': id ~"_help"}) -%} {%- endif -%} + {%- if errors|length > 0 -%} + {%- set attr = attr|merge({'aria-invalid': 'true'}) -%} + {%- endif -%} + {%- set widget_attr = {attr: attr} -%} <{{ element|default('div') }}{% with {attr: row_attr|merge({class: (row_attr.class|default('') ~ ' form-group')|trim})} %}{{ block('attributes') }}{% endwith %}> {{- form_label(form) -}} {{- form_widget(form, widget_attr) -}} diff --git a/src/Symfony/Bridge/Twig/Resources/views/Form/bootstrap_5_horizontal_layout.html.twig b/src/Symfony/Bridge/Twig/Resources/views/Form/bootstrap_5_horizontal_layout.html.twig index 3c24166d48ad0..16a2c4177b490 100644 --- a/src/Symfony/Bridge/Twig/Resources/views/Form/bootstrap_5_horizontal_layout.html.twig +++ b/src/Symfony/Bridge/Twig/Resources/views/Form/bootstrap_5_horizontal_layout.html.twig @@ -23,14 +23,10 @@ {# Rows #} -{% block form_row -%} +{% block form_row_render -%} {%- if expanded is defined and expanded -%} {{ block('fieldset_form_row') }} {%- else -%} - {%- set widget_attr = {} -%} - {%- if help is not empty -%} - {%- set widget_attr = {attr: {'aria-describedby': id ~"_help"}} -%} - {%- endif -%} {%- set row_class = row_class|default(row_attr.class|default('mb-3')) -%} {%- set is_form_floating = is_form_floating|default('form-floating' in row_class) -%} {%- set is_input_group = is_input_group|default('input-group' in row_class) -%} @@ -68,7 +64,7 @@ {%- endif -%} {##}
      {%- endif -%} -{%- endblock form_row %} +{%- endblock form_row_render %} {% block fieldset_form_row -%} {%- set widget_attr = {} -%} diff --git a/src/Symfony/Bridge/Twig/Resources/views/Form/bootstrap_5_layout.html.twig b/src/Symfony/Bridge/Twig/Resources/views/Form/bootstrap_5_layout.html.twig index 17b28fc9ab8d6..7935c3b068d84 100644 --- a/src/Symfony/Bridge/Twig/Resources/views/Form/bootstrap_5_layout.html.twig +++ b/src/Symfony/Bridge/Twig/Resources/views/Form/bootstrap_5_layout.html.twig @@ -320,14 +320,10 @@ {# Rows #} -{%- block form_row -%} +{%- block form_row_render -%} {%- if compound is defined and compound -%} {%- set element = 'fieldset' -%} {%- endif -%} - {%- set widget_attr = {} -%} - {%- if help is not empty -%} - {%- set widget_attr = {attr: {'aria-describedby': id ~"_help"}} -%} - {%- endif -%} {%- set row_class = row_class|default(row_attr.class|default('mb-3')|trim) -%} <{{ element|default('div') }}{% with {attr: row_attr|merge({class: row_class})} %}{{ block('attributes') }}{% endwith %}> {%- if 'form-floating' in row_class -%} @@ -340,7 +336,7 @@ {{- form_help(form) -}} {{- form_errors(form) -}} -{%- endblock form_row %} +{%- endblock form_row_render %} {%- block button_row -%} @@ -352,9 +348,11 @@ {%- block form_errors -%} {%- if errors|length > 0 -%} +
      {%- for error in errors -%}
      {{ error.message }}
      {%- endfor -%} +
      {%- endif %} {%- endblock form_errors %} diff --git a/src/Symfony/Bridge/Twig/Resources/views/Form/form_div_layout.html.twig b/src/Symfony/Bridge/Twig/Resources/views/Form/form_div_layout.html.twig index 537849faebaa4..494829a5fd50a 100644 --- a/src/Symfony/Bridge/Twig/Resources/views/Form/form_div_layout.html.twig +++ b/src/Symfony/Bridge/Twig/Resources/views/Form/form_div_layout.html.twig @@ -366,17 +366,32 @@ {%- endblock repeated_row -%} {%- block form_row -%} - {%- set widget_attr = {} -%} + {%- set attr = {} -%} + {%- set aria_describedby = [] -%} {%- if help is not empty -%} - {%- set widget_attr = {attr: {'aria-describedby': id ~"_help"}} -%} + {%- set aria_describedby = aria_describedby|merge([id ~ "_help"]) -%} {%- endif -%} + {%- if errors|length > 0 -%} + {%- set aria_describedby = aria_describedby|merge([id ~ "_errors"]) -%} + {%- endif -%} + {%- if aria_describedby|length > 0 -%} + {%- set attr = attr|merge({'aria-describedby': aria_describedby|join(' ')}) -%} + {%- endif -%} + {%- if errors|length > 0 -%} + {%- set attr = attr|merge({'aria-invalid': 'true'}) -%} + {%- endif -%} + {%- set widget_attr = {attr: attr} -%} + {{- block('form_row_render') -}} +{%- endblock form_row -%} + +{%- block form_row_render -%} {{- form_label(form) -}} {{- form_errors(form) -}} {{- form_widget(form, widget_attr) -}} {{- form_help(form) -}}
-{%- endblock form_row -%} +{%- endblock form_row_render -%} {%- block button_row -%} @@ -419,7 +434,7 @@ {%- block form_errors -%} {%- if errors|length > 0 -%} -
    +
      {%- for error in errors -%}
    • {{ error.message }}
    • {%- endfor -%} diff --git a/src/Symfony/Bridge/Twig/Resources/views/Form/form_table_layout.html.twig b/src/Symfony/Bridge/Twig/Resources/views/Form/form_table_layout.html.twig index 00a51ab04bc28..108658bc2ccda 100644 --- a/src/Symfony/Bridge/Twig/Resources/views/Form/form_table_layout.html.twig +++ b/src/Symfony/Bridge/Twig/Resources/views/Form/form_table_layout.html.twig @@ -1,10 +1,6 @@ {% use "form_div_layout.html.twig" %} -{%- block form_row -%} - {%- set widget_attr = {} -%} - {%- if help is not empty -%} - {%- set widget_attr = {attr: {'aria-describedby': id ~"_help"}} -%} - {%- endif -%} +{%- block form_row_render -%} {{- form_label(form) -}} @@ -15,7 +11,7 @@ {{- form_help(form) -}} -{%- endblock form_row -%} +{%- endblock form_row_render -%} {%- block button_row -%} diff --git a/src/Symfony/Bridge/Twig/Resources/views/Form/foundation_5_layout.html.twig b/src/Symfony/Bridge/Twig/Resources/views/Form/foundation_5_layout.html.twig index 23e463e6822f0..be6566c5b22f9 100644 --- a/src/Symfony/Bridge/Twig/Resources/views/Form/foundation_5_layout.html.twig +++ b/src/Symfony/Bridge/Twig/Resources/views/Form/foundation_5_layout.html.twig @@ -281,11 +281,7 @@ {# Rows #} -{% block form_row -%} - {%- set widget_attr = {} -%} - {%- if help is not empty -%} - {%- set widget_attr = {attr: {'aria-describedby': id ~"_help"}} -%} - {%- endif -%} +{% block form_row_render -%}
      {{- form_label(form) -}} @@ -294,7 +290,7 @@ {{- form_errors(form) -}}
      -{%- endblock form_row %} +{%- endblock form_row_render %} {% block choice_row -%} {% set force_error = true %} @@ -340,7 +336,7 @@ {% block form_errors -%} {% if errors|length > 0 -%} - {% if form is not rootform %}{% else %}
      {% endif %} + {% if form is not rootform %}{% else %}
      {% endif %} {%- for error in errors -%} {{ error.message }} {% if not loop.last %}, {% endif %} diff --git a/src/Symfony/Bridge/Twig/Resources/views/Form/tailwind_2_layout.html.twig b/src/Symfony/Bridge/Twig/Resources/views/Form/tailwind_2_layout.html.twig index 7f31e70b796c0..66cf126f3620d 100644 --- a/src/Symfony/Bridge/Twig/Resources/views/Form/tailwind_2_layout.html.twig +++ b/src/Symfony/Bridge/Twig/Resources/views/Form/tailwind_2_layout.html.twig @@ -22,7 +22,7 @@ {%- block form_errors -%} {%- if errors|length > 0 -%} -
        +
          {%- for error in errors -%}
        • {{ error.message }}
        • {%- endfor -%} From 0fb1b82d749879ad16db0de873e2fa1503445435 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jean-Fran=C3=A7ois=20Morin-Abdullah?= Date: Thu, 26 Jun 2025 10:26:08 +0200 Subject: [PATCH 2/2] update twig bridge changelog --- src/Symfony/Bridge/Twig/CHANGELOG.md | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/Symfony/Bridge/Twig/CHANGELOG.md b/src/Symfony/Bridge/Twig/CHANGELOG.md index d6d929cb50ed6..fb83ec2aa7084 100644 --- a/src/Symfony/Bridge/Twig/CHANGELOG.md +++ b/src/Symfony/Bridge/Twig/CHANGELOG.md @@ -1,6 +1,10 @@ CHANGELOG ========= +7.4 +--- +* Add `aria-invalid` and `aria-describedby` attributes to form fields when validation errors are present + 7.3 ---