Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fixed #90 -- Added support for switches. #162

Merged
merged 5 commits into from
Nov 5, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,9 @@
# CHANGELOG FOR CRISPY-BOOTSTRAP5

## Next Release

* Added support for [Switches](https://getbootstrap.com/docs/5.2/forms/checks-radios/#switches). (#162)

## 2023.10 (2023-10-2023)
* Added Django 5.0 and 4.2 support
* Added Python 3.11 and 3.12 support
Expand Down
11 changes: 11 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -63,6 +63,17 @@ from crispy_bootstrap5.bootstrap5 import BS5Accordion
)
```

Support is added for [Switches](https://getbootstrap.com/docs/5.2/forms/checks-radios/#switches). Switches are a custom
checkbox rendered as a toggle switch. The widget for these fields should be
a [CheckboxInput](https://docs.djangoproject.com/en/4.2/ref/forms/widgets/#django.forms.CheckboxInput).

```python
from crispy_bootstrap5.bootstrap5 import Switch

... Layout(Switch("is_company"))
```


## Development

To contribute to this library, first checkout the code. Then create a new virtual environment:
Expand Down
4 changes: 4 additions & 0 deletions crispy_bootstrap5/bootstrap5.py
Original file line number Diff line number Diff line change
Expand Up @@ -27,3 +27,7 @@ def __init__(self, *args, **kwargs):
if self.always_open:
for accordion_group in self.fields:
accordion_group.always_open = True


class Switch(Field):
template = "bootstrap5/layout/switch.html"
19 changes: 19 additions & 0 deletions crispy_bootstrap5/templates/bootstrap5/layout/switch.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
{% load crispy_forms_field %}

{% if field.is_hidden %}
{{ field }}
{% else %}
<{% if tag %}{{ tag }}{% else %}div{% endif %} id="div_{{ field.auto_id }}" class="mb-3 form-check form-switch{% if 'form-horizontal' in form_class %} row{% endif %}{% if wrapper_class %} {{ wrapper_class }}{% endif %}{% if field.css_classes %} {{ field.css_classes }}{% endif %}">
<div class="{% for offset in bootstrap_checkbox_offsets %}{{ offset|slice:"7:14" }}{{ offset|slice:"4:7" }}{{ offset|slice:"14:16" }} {% endfor %}{{ field_class }}">
{% if field.errors %}
{% crispy_field field 'class' 'form-check-input is-invalid' 'role' 'checkbox' %}
{% else %}
{% crispy_field field 'class' 'form-check-input' 'role' 'checkbox' %}
{% endif %}
<label for="{{ field.id_for_label }}" class="form-check-label{% if field.field.required %} requiredField{% endif %}">
{{ field.label }}
</label>
{% include 'bootstrap5/layout/help_text_and_errors.html' %}
</div>
</{% if tag %}{{ tag }}{% else %}div{% endif %}>
{% endif %}
9 changes: 9 additions & 0 deletions tests/results/test_switch.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
<form method="post">
<div id="div_id_is_company" class="mb-3 form-check form-switch">
<div class="">
<input type="checkbox" name="is_company" class="checkboxinput form-check-input" role="checkbox" id="id_is_company" />
<label for="id_is_company" class="form-check-label">company</label>
<div id="id_is_company_helptext" class="form-text">is_company help text</div>
</div>
</div>
</form>
13 changes: 13 additions & 0 deletions tests/results/test_switch_horizontal.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
<form class="form-horizontal" method="post">
<div id="div_id_is_company" class="mb-3 form-check form-switch row">
<div class="offset-lg-2 col-lg-8">
<input type="checkbox" name="is_company" class="checkboxinput form-check-input" role="checkbox" id="id_is_company" />
<label for="id_is_company" class="form-check-label">company</label>
<div id="id_is_company_helptext" class="form-text">is_company help text</div>
</div>
</div>
<div id="div_id_first_name" class="mb-3 row">
<label for="id_first_name" class="col-form-label col-lg-2 requiredField">first name<span class="asteriskField">*</span> </label>
<div class="col-lg-8"><input type="text" name="first_name" maxlength="5" class="textinput textInput inputtext form-control" required id="id_first_name" /></div>
</div>
</form>
19 changes: 18 additions & 1 deletion tests/test_layout_objects.py
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@
from django.utils.translation import activate, deactivate
from django.utils.translation import gettext as _

from crispy_bootstrap5.bootstrap5 import BS5Accordion, FloatingField
from crispy_bootstrap5.bootstrap5 import BS5Accordion, FloatingField, Switch

from .forms import (
CheckboxesSampleForm,
Expand Down Expand Up @@ -604,3 +604,20 @@ def test_grouped_checkboxes_radios(self):
else:
expected = "test_grouped_radios_failing.html"
assert parse_form(form) == parse_expected(expected)

def test_switch(self):
form = SampleForm()
form["is_company"].help_text = "is_company help text"
form.helper = FormHelper()
form.helper.layout = Layout(Switch("is_company"))
assert parse_form(form) == parse_expected("test_switch.html")

def test_switch_horizontal(self):
form = SampleForm()
form["is_company"].help_text = "is_company help text"
form.helper = FormHelper()
form.helper.label_class = "col-lg-2"
form.helper.field_class = "col-lg-8"
form.helper.form_class = "form-horizontal"
form.helper.layout = Layout(Switch("is_company"), "first_name")
assert parse_form(form) == parse_expected("test_switch_horizontal.html")