mirror of
https://github.com/django/django.git
synced 2024-12-22 00:55:44 +00:00
Refs #32819 -- Added aria-describedby property to BoundField.
This commit is contained in:
parent
27375ad50e
commit
1e05431881
@ -289,20 +289,24 @@ class BoundField(RenderableFieldMixin):
|
||||
attrs["disabled"] = True
|
||||
if not widget.is_hidden and self.errors:
|
||||
attrs["aria-invalid"] = "true"
|
||||
# If a custom aria-describedby attribute is given (either via the attrs
|
||||
# argument or widget.attrs) and help_text is used, the custom
|
||||
# aria-described by is preserved so user can set the desired order.
|
||||
if (
|
||||
not attrs.get("aria-describedby")
|
||||
and not widget.attrs.get("aria-describedby")
|
||||
and self.field.help_text
|
||||
and not self.use_fieldset
|
||||
and self.auto_id
|
||||
and not self.is_hidden
|
||||
):
|
||||
attrs["aria-describedby"] = f"{self.auto_id}_helptext"
|
||||
# Preserve aria-describedby provided by the attrs argument so user
|
||||
# can set the desired order.
|
||||
if not attrs.get("aria-describedby") and not self.use_fieldset:
|
||||
if aria_describedby := self.aria_describedby:
|
||||
attrs["aria-describedby"] = aria_describedby
|
||||
return attrs
|
||||
|
||||
@property
|
||||
def aria_describedby(self):
|
||||
# Preserve aria-describedby set on the widget.
|
||||
if self.field.widget.attrs.get("aria-describedby"):
|
||||
return None
|
||||
aria_describedby = []
|
||||
if self.auto_id and not self.is_hidden:
|
||||
if self.help_text:
|
||||
aria_describedby.append(f"{self.auto_id}_helptext")
|
||||
return " ".join(aria_describedby)
|
||||
|
||||
@property
|
||||
def widget_type(self):
|
||||
return re.sub(
|
||||
|
@ -1,5 +1,5 @@
|
||||
{% if field.use_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 %}>
|
||||
<fieldset{% if field.aria_describedby %} aria-describedby="{{ field.aria_describedby }}"{% endif %}>
|
||||
{% if field.label %}{{ field.legend_tag() }}{% endif %}
|
||||
{% else %}
|
||||
{% if field.label %}{{ field.label_tag() }}{% endif %}
|
||||
|
@ -1,5 +1,5 @@
|
||||
{% if field.use_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 %}>
|
||||
<fieldset{% if field.aria_describedby %} aria-describedby="{{ field.aria_describedby }}"{% endif %}>
|
||||
{% if field.label %}{{ field.legend_tag }}{% endif %}
|
||||
{% else %}
|
||||
{% if field.label %}{{ field.label_tag }}{% endif %}
|
||||
|
@ -1161,6 +1161,15 @@ The field-specific output honors the form object's ``auto_id`` setting:
|
||||
Attributes of ``BoundField``
|
||||
----------------------------
|
||||
|
||||
.. attribute:: BoundField.aria_describedby
|
||||
|
||||
.. versionadded:: 5.2
|
||||
|
||||
Returns an ``aria-describedby`` reference to associate a field with its
|
||||
help text. Returns ``None`` if ``aria-describedby`` is set in
|
||||
:attr:`Widget.attrs` to preserve the user defined attribute when rendering
|
||||
the form.
|
||||
|
||||
.. attribute:: BoundField.auto_id
|
||||
|
||||
The HTML ID attribute for this ``BoundField``. Returns an empty string
|
||||
|
@ -256,6 +256,9 @@ Forms
|
||||
HTML ``id`` attribute to be added in the error template. See
|
||||
:attr:`.ErrorList.field_id` for details.
|
||||
|
||||
* An :attr:`~django.forms.BoundField.aria_describedby` property is added to
|
||||
``BoundField`` to ease use of this HTML attribute in templates.
|
||||
|
||||
Generic Views
|
||||
~~~~~~~~~~~~~
|
||||
|
||||
|
@ -4801,6 +4801,34 @@ Options: <select multiple name="options" aria-invalid="true" required>
|
||||
with self.assertRaises(KeyError):
|
||||
f["name"]
|
||||
|
||||
def test_aria_describedby_property(self):
|
||||
class TestForm(Form):
|
||||
name = CharField(help_text="Some help text")
|
||||
|
||||
form = TestForm({"name": "MyName"})
|
||||
self.assertEqual(form["name"].aria_describedby, "id_name_helptext")
|
||||
|
||||
form = TestForm(auto_id=None)
|
||||
self.assertEqual(form["name"].aria_describedby, "")
|
||||
|
||||
class TestFormHidden(Form):
|
||||
name = CharField(help_text="Some help text", widget=HiddenInput)
|
||||
|
||||
form = TestFormHidden()
|
||||
self.assertEqual(form["name"].aria_describedby, "")
|
||||
|
||||
class TestFormWithAttrs(Form):
|
||||
name = CharField(widget=TextInput(attrs={"aria-describedby": "my-id"}))
|
||||
|
||||
form = TestFormWithAttrs({"name": "MyName"})
|
||||
self.assertIs(form["name"].aria_describedby, None)
|
||||
|
||||
class TestFormWithoutHelpText(Form):
|
||||
name = CharField()
|
||||
|
||||
form = TestFormWithoutHelpText()
|
||||
self.assertEqual(form["name"].aria_describedby, "")
|
||||
|
||||
|
||||
@jinja2_tests
|
||||
class Jinja2FormsTestCase(FormsTestCase):
|
||||
|
Loading…
Reference in New Issue
Block a user