Skip to content

Commit ce8ef0f

Browse files
xidyve
andauthored
Fix help text and error IDs for aria-describedby (#746)
* Fix help text and error IDs for aria-describedby Django recently started using `aria-describedby` to associate form fields first with their help texts, and later also with error messages. In #716, django-bootstrap5 was adapted to also include those the necessary IDs in templates. `aria-describedby` for fields can have different values: - `"{field.auto_id}_helptext"` - `"{field.auto_id}_error"` - both of them - a user defined value that is left unchanged The approach in #716 was to use the value from `aria-describedby` for the ID of the help text. Unfortunately, this only works in the first case. So I propose to solve this the same way the django templates solve this and just hardcode the IDs. * fix tests for django 5.2 * fix tests --------- Co-authored-by: Dylan Verheul <[email protected]>
1 parent de619a5 commit ce8ef0f

File tree

6 files changed

+22
-11
lines changed

6 files changed

+22
-11
lines changed

src/django_bootstrap5/renderers.py

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -394,14 +394,12 @@ def get_help_html(self):
394394
"""Return HTML for help text."""
395395
help_text = self.help_text or ""
396396
if help_text:
397-
widget_attrs = self.field.build_widget_attrs(self.widget.attrs)
398-
aria_describedby = widget_attrs.get("aria-describedby")
399397
return render_template_file(
400398
self.field_help_text_template,
401399
context={
402400
"field": self.field,
403401
"help_text": help_text,
404-
"id_help_text": aria_describedby,
402+
"id_help_text": f"{self.field.auto_id}_helptext",
405403
"layout": self.layout,
406404
"show_help": self.show_help,
407405
},
Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,7 @@
1-
{% for text in field_errors %}
2-
<div class="invalid-feedback">{{ text }}</div>
3-
{% endfor %}
1+
{% if field_errors %}
2+
<div id="{{ field.auto_id }}_error">
3+
{% for text in field_errors %}
4+
<div class="invalid-feedback">{{ text }}</div>
5+
{% endfor %}
6+
</div>
7+
{% endif %}

tests/test_bootstrap_field.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -37,7 +37,7 @@ def test_help_text_overridden_aria_describedby(self):
3737
form = SubjectTestForm()
3838
form.fields["subject"].widget.attrs["aria-describedby"] = "my_id"
3939
html = self.render("{% bootstrap_field form.subject %}", {"form": form})
40-
self.assertIn('<div id="my_id" class="form-text">my_help_text</div>', html)
40+
self.assertIn('<div id="id_subject_helptext" class="form-text">my_help_text</div>', html)
4141

4242
def test_placeholder(self):
4343
html = self.render("{% bootstrap_field form.subject %}", {"form": SubjectTestForm()})

tests/test_bootstrap_field_input_checkbox.py

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,16 +30,20 @@ def test_input_type_checkbox_is_invalid(self):
3030
)
3131
if DJANGO_VERSION >= "5":
3232
html = html.replace(' aria-invalid="true"', "")
33+
if DJANGO_VERSION >= "5.2":
34+
html = html.replace(' aria-describedby="id_test_error"', "")
3335
self.assertHTMLEqual(
3436
html,
3537
(
3638
'<div class="django_bootstrap5-err django_bootstrap5-req mb-3">'
3739
'<div class="form-check">'
3840
'<input class="form-check-input is-invalid" id="id_test" name="test" required type="checkbox">'
3941
'<label class="form-check-label" for="id_test">Test</label>'
42+
'<div id="id_test_error">'
4043
'<div class="invalid-feedback">This field is required.</div>'
4144
"</div>"
4245
"</div>"
46+
"</div>"
4347
),
4448
)
4549

tests/test_bootstrap_field_input_text.py

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,8 @@ def test_input_type_text(self):
3333
html = self.render("{% bootstrap_field form.test %}", context={"form": form})
3434
if DJANGO_VERSION >= "5":
3535
html = html.replace(' aria-invalid="true"', "")
36+
if DJANGO_VERSION >= "5.2":
37+
html = html.replace(' aria-describedby="id_test_error"', "")
3638

3739
self.assertHTMLEqual(
3840
html,
@@ -41,8 +43,10 @@ def test_input_type_text(self):
4143
'<label class="form-label" for="id_test">Test</label>'
4244
'<input type="text" name="test"'
4345
' class="form-control is-invalid" placeholder="Test" required id="id_test">'
46+
'<div id="id_test_error">'
4447
'<div class="invalid-feedback">This field is required.</div>'
4548
"</div>"
49+
"</div>"
4650
),
4751
)
4852

@@ -185,6 +189,8 @@ def test_input_validation_failure(self):
185189
html = self.render('{% bootstrap_field form.test addon_before="foo" %}', context={"form": form})
186190
if DJANGO_VERSION >= "5":
187191
html = html.replace(' aria-invalid="true"', "")
192+
if DJANGO_VERSION >= "5.2":
193+
html = html.replace(' aria-describedby="id_test_error"', "")
188194

189195
self.assertHTMLEqual(
190196
html,
@@ -195,9 +201,11 @@ def test_input_validation_failure(self):
195201
'<span class="input-group-text">foo</span>'
196202
'<input type="text" name="test" minlength="1" class="form-control'
197203
' is-invalid" placeholder="Test" required id="id_test">'
204+
'<div id="id_test_error">'
198205
'<div class="invalid-feedback">This field is required.</div>'
199206
"</div>"
200207
"</div>"
208+
"</div>"
201209
),
202210
)
203211

tests/test_bootstrap_form.py

Lines changed: 1 addition & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -38,17 +38,14 @@ def test_exclude(self):
3838
)
3939
if DJANGO_VERSION >= "5":
4040
html = html.replace(' aria-describedby="id_required_text_helptext"', "")
41-
help_text = '<div id="id_required_text_helptext" class="form-text"><i>required_text_help</i>'
42-
else:
43-
help_text = '<div class="form-text"><i>required_text_help</i>'
4441
self.assertHTMLEqual(
4542
html,
4643
(
4744
'<div class="mb-3 django_bootstrap5-req">'
4845
'<label class="form-label" for="id_required_text">Required text</label>'
4946
'<input type="text" name="required_text" class="form-control"'
5047
' placeholder="Required text" required id="id_required_text">'
51-
f"{help_text}"
48+
'<div id="id_required_text_helptext" class="form-text"><i>required_text_help</i>'
5249
"</div>"
5350
),
5451
)

0 commit comments

Comments
 (0)