diff --git a/gadjo/templates/gadjo/widget.html b/gadjo/templates/gadjo/widget.html index 6bde427..6495955 100644 --- a/gadjo/templates/gadjo/widget.html +++ b/gadjo/templates/gadjo/widget.html @@ -21,7 +21,7 @@ {% block widget-attrs %}{% endblock %}> {% block widget-hint %} {% if field.help_text %} -
+
{% for error in field.errors %}
{{ error }}{% if not forloop.last %}
{% endif %}
{% endfor %}
diff --git a/gadjo/templatetags/gadjo.py b/gadjo/templatetags/gadjo.py
index f951ba7..d3e33e9 100644
--- a/gadjo/templatetags/gadjo.py
+++ b/gadjo/templatetags/gadjo.py
@@ -108,6 +108,14 @@ def with_template(form):
templates = ['gadjo/widget.html']
if hasattr(widget, 'input_type'):
templates.insert(0, 'gadjo/%s-widget.html' % widget.input_type)
+ aria_described_by = []
+ if field.field.help_text:
+ aria_described_by.append(f'help_text_{field.id_for_label}')
+ if field.errors:
+ aria_described_by.append(f'error_{field.id_for_label}')
+ field.field.widget.attrs['aria-invalid'] = 'true'
+ if aria_described_by:
+ field.field.widget.attrs['aria-describedby'] = ' '.join(aria_described_by)
fields_with_templates.append(
(
field,
diff --git a/tests/project/settings.py b/tests/project/settings.py
index 93c3e96..8b970a5 100644
--- a/tests/project/settings.py
+++ b/tests/project/settings.py
@@ -28,6 +28,7 @@ INSTALLED_APPS = [
"django.contrib.auth",
"django.contrib.contenttypes",
"django.contrib.sites",
+ "gadjo",
]
STATIC_URL = "/static/"
SITE_ID = 1
diff --git a/tests/test_templatetags.py b/tests/test_templatetags.py
index e892d39..9057188 100644
--- a/tests/test_templatetags.py
+++ b/tests/test_templatetags.py
@@ -1,8 +1,10 @@
import html
import urllib
+from django import forms
from django.template import Context, Template
from django.test.client import RequestFactory
+from pyquery import PyQuery
def test_start_timestamp():
@@ -32,3 +34,40 @@ def test_querystring():
assert urllib.parse.parse_qs(urllib.parse.urlparse(html.unescape(t.render(ctx))).query) == {
'name': ['Ayers']
}
+
+
+def test_with_template():
+ class ExampleForm(forms.Form):
+ text = forms.CharField(label='Text', max_length=50)
+
+ request = RequestFactory().get('/')
+ t = Template('{{ form|with_template }}')
+ ctx = Context({'request': request, 'form': ExampleForm()})
+ rendered = t.render(ctx)
+ assert PyQuery(rendered).find('input[type=text]')
+ assert not PyQuery(rendered).find('input[type=text]').attr['aria-invalid']
+
+ ctx = Context({'request': request, 'form': ExampleForm(data=request.GET)})
+ rendered = t.render(ctx)
+ assert (
+ PyQuery(rendered).find('input[type=text][aria-describedby]').attr['aria-describedby']
+ == 'error_id_text'
+ )
+ assert PyQuery(rendered).find('input[type=text]').attr['aria-invalid']
+
+ class ExampleForm(forms.Form):
+ text = forms.CharField(label='Text', max_length=50, help_text='Help text')
+
+ ctx = Context({'request': request, 'form': ExampleForm()})
+ rendered = t.render(ctx)
+ assert (
+ PyQuery(rendered).find('input[type=text][aria-describedby]').attr['aria-describedby']
+ == 'help_text_id_text'
+ )
+
+ ctx = Context({'request': request, 'form': ExampleForm(data=request.GET)})
+ rendered = t.render(ctx)
+ assert (
+ PyQuery(rendered).find('input[type=text][aria-describedby]').attr['aria-describedby']
+ == 'help_text_id_text error_id_text'
+ )
diff --git a/tox.ini b/tox.ini
index 5ce7e44..4b63f84 100644
--- a/tox.ini
+++ b/tox.ini
@@ -16,6 +16,7 @@ deps =
WebTest
psycopg2-binary
psycopg2
+ pyquery
codestyle: pre-commit
coverage: pytest-cov
pylint: pylint