Skip to content

Commit 38aa660

Browse files
committed
add a custom boolean field that renders the checkboxes component
This allows us to have fields that return a boolean, and render as a single checkbox, equivalent to the built in BooleanField. An example is when recording a symptom, we have fields like "The symptom is intermittent" and "The symptom has recently resolved" which are each individual fields and are not grouped within a fieldset with a common legend.
1 parent 3974cf2 commit 38aa660

File tree

4 files changed

+161
-0
lines changed

4 files changed

+161
-0
lines changed

manage_breast_screening/nhsuk_forms/fields/__init__.py

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,11 @@
1+
from .boolean_field import BooleanField
12
from .char_field import CharField
23
from .choice_fields import ChoiceField, MultipleChoiceField
34
from .integer_field import IntegerField
45
from .split_date_field import SplitDateField
56

67
__all__ = [
8+
"BooleanField",
79
"CharField",
810
"IntegerField",
911
"ChoiceField",
Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
from django import forms
2+
3+
from .choice_fields import BoundChoiceField
4+
5+
6+
class BooleanField(forms.BooleanField):
7+
bound_field_class = BoundChoiceField
8+
9+
def __init__(
10+
self,
11+
*args,
12+
hint=None,
13+
label_classes=None,
14+
classes=None,
15+
**kwargs,
16+
):
17+
kwargs["template_name"] = "forms/single-checkbox.jinja"
18+
19+
self.hint = hint
20+
self.classes = classes
21+
self.label_classes = label_classes
22+
23+
super().__init__(*args, **kwargs)
Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
{% from 'nhsuk/components/checkboxes/macro.jinja' import checkboxes %}
2+
{% set unbound_field = field.field %}
3+
{% if field.errors %}
4+
{% set error_message = {"text": field.errors | first} %}
5+
{% endif %}
6+
{% set conditional_html = field.conditional_html(value) %}
7+
{% set widget = unbound_field.widget %}
8+
9+
{{ checkboxes({
10+
"name": field.html_name,
11+
"idPrefix": field.auto_id,
12+
"errorMessage": error_message,
13+
"hint": {
14+
"html": unbound_field.hint|e
15+
} if unbound_field.hint,
16+
"items": [
17+
{
18+
"id": field.auto_id,
19+
"value": "true",
20+
"text": field.label,
21+
"checked": widget.check_test(field.value()),
22+
"conditional": {
23+
"html": conditional_html
24+
} if conditional_html else undefined
25+
}
26+
]
27+
}) }}
Lines changed: 109 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,109 @@
1+
import pytest
2+
from django.forms import Form
3+
from pytest_django.asserts import assertHTMLEqual
4+
5+
from ...fields import BooleanField
6+
7+
8+
class TestBooelanField:
9+
@pytest.fixture
10+
def form_class(self):
11+
class TestForm(Form):
12+
field = BooleanField(
13+
label="Abc",
14+
hint="Click me",
15+
label_classes="extra-class",
16+
required=False,
17+
)
18+
19+
return TestForm
20+
21+
def test_renders_checkbox(self, form_class):
22+
assertHTMLEqual(
23+
form_class()["field"].as_field_group(),
24+
"""
25+
<div class="nhsuk-form-group">
26+
<div class="nhsuk-hint" id="id_field-hint">
27+
Click me
28+
</div>
29+
<div class="nhsuk-checkboxes" data-module="nhsuk-checkboxes">
30+
<div class="nhsuk-checkboxes__item">
31+
<input class="nhsuk-checkboxes__input" id="id_field" name="field" type="checkbox" value="true">
32+
<label class="nhsuk-label nhsuk-checkboxes__label" for="id_field">Abc</label>
33+
</div>
34+
</div>
35+
</div>
36+
""",
37+
)
38+
39+
def test_renders_with_data_true(self, form_class):
40+
assertHTMLEqual(
41+
form_class(data={"field": "true"})["field"].as_field_group(),
42+
"""
43+
<div class="nhsuk-form-group">
44+
<div class="nhsuk-hint" id="id_field-hint">
45+
Click me
46+
</div>
47+
<div class="nhsuk-checkboxes" data-module="nhsuk-checkboxes">
48+
<div class="nhsuk-checkboxes__item">
49+
<input checked class="nhsuk-checkboxes__input" id="id_field" name="field" type="checkbox" value="true">
50+
<label class="nhsuk-label nhsuk-checkboxes__label" for="id_field">Abc</label>
51+
</div>
52+
</div>
53+
</div>
54+
""",
55+
)
56+
57+
def test_renders_with_data_false(self, form_class):
58+
assertHTMLEqual(
59+
form_class(data={"field": "false"})["field"].as_field_group(),
60+
"""
61+
<div class="nhsuk-form-group">
62+
<div class="nhsuk-hint" id="id_field-hint">
63+
Click me
64+
</div>
65+
<div class="nhsuk-checkboxes" data-module="nhsuk-checkboxes">
66+
<div class="nhsuk-checkboxes__item">
67+
<input class="nhsuk-checkboxes__input" id="id_field" name="field" type="checkbox" value="true">
68+
<label class="nhsuk-label nhsuk-checkboxes__label" for="id_field">Abc</label>
69+
</div>
70+
</div>
71+
</div>
72+
""",
73+
)
74+
75+
def test_renders_with_initial_true(self, form_class):
76+
assertHTMLEqual(
77+
form_class(initial={"field": True})["field"].as_field_group(),
78+
"""
79+
<div class="nhsuk-form-group">
80+
<div class="nhsuk-hint" id="id_field-hint">
81+
Click me
82+
</div>
83+
<div class="nhsuk-checkboxes" data-module="nhsuk-checkboxes">
84+
<div class="nhsuk-checkboxes__item">
85+
<input checked class="nhsuk-checkboxes__input" id="id_field" name="field" type="checkbox" value="true">
86+
<label class="nhsuk-label nhsuk-checkboxes__label" for="id_field">Abc</label>
87+
</div>
88+
</div>
89+
</div>
90+
""",
91+
)
92+
93+
def test_renders_with_initial_false(self, form_class):
94+
assertHTMLEqual(
95+
form_class(initial={"field": False})["field"].as_field_group(),
96+
"""
97+
<div class="nhsuk-form-group">
98+
<div class="nhsuk-hint" id="id_field-hint">
99+
Click me
100+
</div>
101+
<div class="nhsuk-checkboxes" data-module="nhsuk-checkboxes">
102+
<div class="nhsuk-checkboxes__item">
103+
<input class="nhsuk-checkboxes__input" id="id_field" name="field" type="checkbox" value="true">
104+
<label class="nhsuk-label nhsuk-checkboxes__label" for="id_field">Abc</label>
105+
</div>
106+
</div>
107+
</div>
108+
""",
109+
)

0 commit comments

Comments
 (0)