mirror of
https://github.com/django/django.git
synced 2025-06-05 11:39:13 +00:00
Refs #32819 -- Established relationship between form fieldsets and their help text.
This adds aria-describedby for widgets rendered in a fieldset such as radios. aria-describedby for these widgets is added to the <fieldset> element rather than each <input>.
This commit is contained in:
parent
557fa51837
commit
eec7e9ba89
@ -1,5 +1,5 @@
|
|||||||
{% if field.use_fieldset %}
|
{% if field.use_fieldset %}
|
||||||
<fieldset>
|
<fieldset{% if field.help_text and field.auto_id and "aria-describedby" not in field.field.widget.attrs %} aria-describedby="{{ field.auto_id }}_helptext"{% endif %}>
|
||||||
{% if field.label %}{{ field.legend_tag() }}{% endif %}
|
{% if field.label %}{{ field.legend_tag() }}{% endif %}
|
||||||
{% else %}
|
{% else %}
|
||||||
{% if field.label %}{{ field.label_tag() }}{% endif %}
|
{% if field.label %}{{ field.label_tag() }}{% endif %}
|
||||||
|
@ -1,10 +1,9 @@
|
|||||||
{% if field.use_fieldset %}
|
{% if field.use_fieldset %}
|
||||||
<fieldset>
|
<fieldset{% if field.help_text and field.auto_id and "aria-describedby" not in field.field.widget.attrs %} aria-describedby="{{ field.auto_id }}_helptext"{% endif %}>
|
||||||
{% if field.label %}{{ field.legend_tag }}{% endif %}
|
{% if field.label %}{{ field.legend_tag }}{% endif %}
|
||||||
{% else %}
|
{% else %}
|
||||||
{% if field.label %}{{ field.label_tag }}{% endif %}
|
{% if field.label %}{{ field.label_tag }}{% endif %}
|
||||||
{% endif %}
|
{% endif %}
|
||||||
{% if field.help_text %}<div class="helptext"{% if field.auto_id %} id="{{ field.auto_id }}_helptext"{% endif %}>{{ field.help_text|safe }}</div>{% endif %}
|
{% if field.help_text %}<div class="helptext"{% if field.auto_id %} id="{{ field.auto_id }}_helptext"{% endif %}>{{ field.help_text|safe }}</div>{% endif %}
|
||||||
{{ field.errors }}
|
{{ field.errors }}
|
||||||
{{ field }}
|
{{ field }}{% if field.use_fieldset %}</fieldset>{% endif %}
|
||||||
{% if field.use_fieldset %}</fieldset>{% endif %}
|
|
||||||
|
@ -283,9 +283,10 @@ fields. We've specified ``auto_id=False`` to simplify the output:
|
|||||||
<div>Sender:<div class="helptext">A valid email address, please.</div><input type="email" name="sender" required></div>
|
<div>Sender:<div class="helptext">A valid email address, please.</div><input type="email" name="sender" required></div>
|
||||||
<div>Cc myself:<input type="checkbox" name="cc_myself"></div>
|
<div>Cc myself:<input type="checkbox" name="cc_myself"></div>
|
||||||
|
|
||||||
When a field has help text and the widget is not rendered in a ``<fieldset>``,
|
When a field has help text it is associated with its input using the
|
||||||
``aria-describedby`` is added to the ``<input>`` to associate it to the
|
``aria-describedby`` HTML attribute. If the widget is rendered in a
|
||||||
help text:
|
``<fieldset>`` then ``aria-describedby`` is added to this element, otherwise it
|
||||||
|
is added to the widget's ``<input>``:
|
||||||
|
|
||||||
.. code-block:: pycon
|
.. code-block:: pycon
|
||||||
|
|
||||||
@ -325,6 +326,10 @@ inside ``aria-describedby``:
|
|||||||
|
|
||||||
``aria-describedby`` was added to associate ``help_text`` with its input.
|
``aria-describedby`` was added to associate ``help_text`` with its input.
|
||||||
|
|
||||||
|
.. versionchanged:: 5.1
|
||||||
|
|
||||||
|
``aria-describedby`` support was added for ``<fieldset>``.
|
||||||
|
|
||||||
``error_messages``
|
``error_messages``
|
||||||
------------------
|
------------------
|
||||||
|
|
||||||
|
@ -138,7 +138,9 @@ File Uploads
|
|||||||
Forms
|
Forms
|
||||||
~~~~~
|
~~~~~
|
||||||
|
|
||||||
* ...
|
* In order to improve accessibility and enable screen readers to associate
|
||||||
|
fieldsets with their help text, the form fieldset now includes the
|
||||||
|
``aria-describedby`` HTML attribute.
|
||||||
|
|
||||||
Generic Views
|
Generic Views
|
||||||
~~~~~~~~~~~~~
|
~~~~~~~~~~~~~
|
||||||
|
@ -3114,6 +3114,83 @@ Options: <select multiple name="options" aria-invalid="true" required>
|
|||||||
'required aria-describedby="id_username_helptext"></div>',
|
'required aria-describedby="id_username_helptext"></div>',
|
||||||
)
|
)
|
||||||
|
|
||||||
|
def test_fieldset_aria_describedby(self):
|
||||||
|
class FieldsetForm(Form):
|
||||||
|
checkbox = MultipleChoiceField(
|
||||||
|
choices=[("a", "A"), ("b", "B")],
|
||||||
|
widget=CheckboxSelectMultiple,
|
||||||
|
help_text="Checkbox help text",
|
||||||
|
)
|
||||||
|
radio = MultipleChoiceField(
|
||||||
|
choices=[("a", "A"), ("b", "B")],
|
||||||
|
widget=RadioSelect,
|
||||||
|
help_text="Radio help text",
|
||||||
|
)
|
||||||
|
datetime = SplitDateTimeField(help_text="Enter Date and Time")
|
||||||
|
|
||||||
|
f = FieldsetForm()
|
||||||
|
self.assertHTMLEqual(
|
||||||
|
str(f),
|
||||||
|
'<div><fieldset aria-describedby="id_checkbox_helptext">'
|
||||||
|
"<legend>Checkbox:</legend>"
|
||||||
|
'<div class="helptext" id="id_checkbox_helptext">Checkbox help text</div>'
|
||||||
|
'<div id="id_checkbox"><div>'
|
||||||
|
'<label for="id_checkbox_0"><input type="checkbox" name="checkbox" '
|
||||||
|
'value="a" id="id_checkbox_0" /> A</label>'
|
||||||
|
"</div><div>"
|
||||||
|
'<label for="id_checkbox_1"><input type="checkbox" name="checkbox" '
|
||||||
|
'value="b" id="id_checkbox_1" /> B</label>'
|
||||||
|
"</div></div></fieldset></div>"
|
||||||
|
'<div><fieldset aria-describedby="id_radio_helptext">'
|
||||||
|
"<legend>Radio:</legend>"
|
||||||
|
'<div class="helptext" id="id_radio_helptext">Radio help text</div>'
|
||||||
|
'<div id="id_radio"><div>'
|
||||||
|
'<label for="id_radio_0"><input type="radio" name="radio" value="a" '
|
||||||
|
'required id="id_radio_0" />A</label>'
|
||||||
|
"</div><div>"
|
||||||
|
'<label for="id_radio_1"><input type="radio" name="radio" value="b" '
|
||||||
|
'required id="id_radio_1" /> B</label>'
|
||||||
|
"</div></div></fieldset></div>"
|
||||||
|
'<div><fieldset aria-describedby="id_datetime_helptext">'
|
||||||
|
"<legend>Datetime:</legend>"
|
||||||
|
'<div class="helptext" id="id_datetime_helptext">Enter Date and Time</div>'
|
||||||
|
'<input type="text" name="datetime_0" required id="id_datetime_0" />'
|
||||||
|
'<input type="text" name="datetime_1" required id="id_datetime_1" />'
|
||||||
|
"</fieldset></div>",
|
||||||
|
)
|
||||||
|
f = FieldsetForm(auto_id=False)
|
||||||
|
# aria-describedby is not included.
|
||||||
|
self.assertIn("<fieldset>", str(f))
|
||||||
|
self.assertIn('<div class="helptext">', str(f))
|
||||||
|
f = FieldsetForm(auto_id="custom_%s")
|
||||||
|
# aria-describedby uses custom auto_id.
|
||||||
|
self.assertIn('fieldset aria-describedby="custom_checkbox_helptext"', str(f))
|
||||||
|
self.assertIn('<div class="helptext" id="custom_checkbox_helptext">', str(f))
|
||||||
|
|
||||||
|
def test_fieldset_custom_aria_describedby(self):
|
||||||
|
# aria-describedby set on widget results in aria-describedby being
|
||||||
|
# added to widget and not the <fieldset>.
|
||||||
|
class FieldsetForm(Form):
|
||||||
|
checkbox = MultipleChoiceField(
|
||||||
|
choices=[("a", "A"), ("b", "B")],
|
||||||
|
widget=CheckboxSelectMultiple(attrs={"aria-describedby": "custom-id"}),
|
||||||
|
help_text="Checkbox help text",
|
||||||
|
)
|
||||||
|
|
||||||
|
f = FieldsetForm()
|
||||||
|
self.assertHTMLEqual(
|
||||||
|
str(f),
|
||||||
|
"<div><fieldset><legend>Checkbox:</legend>"
|
||||||
|
'<div class="helptext" id="id_checkbox_helptext">Checkbox help text</div>'
|
||||||
|
'<div id="id_checkbox"><div>'
|
||||||
|
'<label for="id_checkbox_0"><input type="checkbox" name="checkbox" '
|
||||||
|
'value="a" aria-describedby="custom-id" id="id_checkbox_0" />A</label>'
|
||||||
|
"</div><div>"
|
||||||
|
'<label for="id_checkbox_1"><input type="checkbox" name="checkbox" '
|
||||||
|
'value="b" aria-describedby="custom-id" id="id_checkbox_1" />B</label>'
|
||||||
|
"</div></div></fieldset></div>",
|
||||||
|
)
|
||||||
|
|
||||||
def test_as_widget_custom_aria_describedby(self):
|
def test_as_widget_custom_aria_describedby(self):
|
||||||
class FoodForm(Form):
|
class FoodForm(Form):
|
||||||
intl_name = CharField(help_text="The food's international name.")
|
intl_name = CharField(help_text="The food's international name.")
|
||||||
|
Loading…
x
Reference in New Issue
Block a user