Skip to content

Commit

Permalink
Support basic addons like in django-bootstrap4
Browse files Browse the repository at this point in the history
  • Loading branch information
dyve committed Apr 30, 2021
1 parent 633e998 commit 287cc3e
Show file tree
Hide file tree
Showing 3 changed files with 46 additions and 15 deletions.
1 change: 1 addition & 0 deletions docs/forms.rst
Original file line number Diff line number Diff line change
Expand Up @@ -63,6 +63,7 @@ Floating labels are supported for widgets that can use `form-control`, with the

- `FileInput` and its descendants
- `TextInput` with type `color`
- Fields that have `addon_before` or `addon_after` defined

The `Select` widget can only float if it has the default size, does not support multiple selects, and has no special markup.

Expand Down
41 changes: 26 additions & 15 deletions src/django_bootstrap5/renderers.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,16 +9,7 @@
RadioSelect,
Select,
)
from django.forms.widgets import (
EmailInput,
Input,
NumberInput,
PasswordInput,
SelectMultiple,
Textarea,
TextInput,
URLInput,
)
from django.forms.widgets import Input, SelectMultiple, Textarea
from django.utils.html import conditional_escape, format_html, strip_tags
from django.utils.safestring import mark_safe

Expand Down Expand Up @@ -269,7 +260,12 @@ def __init__(self, field, *args, **kwargs):

@property
def is_floating(self):
return super().is_floating and self.can_widget_float(self.widget)
return (
super().is_floating
and self.can_widget_float(self.widget)
and not self.addon_before
and not self.addon_after
)

@property
def default_placeholder(self):
Expand All @@ -283,9 +279,9 @@ def get_widget_input_type(self, widget):
"""Return input type of widget, or None."""
return widget.input_type if isinstance(widget, Input) else None

def can_widget_float(self, widget):
"""Return whether given widget can be set to `form-floating` behavior."""
if isinstance(widget, (TextInput, NumberInput, EmailInput, URLInput, PasswordInput)):
def is_form_control_widget(self, widget=None):
widget = widget or self.widget
if isinstance(widget, Input):
return self.get_widget_input_type(widget) in [
"text",
"number",
Expand All @@ -296,7 +292,12 @@ def can_widget_float(self, widget):
"time",
"password",
]
if isinstance(widget, Textarea):

return isinstance(widget, Textarea)

def can_widget_float(self, widget):
"""Return whether given widget can be set to `form-floating` behavior."""
if self.is_form_control_widget(widget):
return True
if isinstance(widget, Select):
return self.size == DEFAULT_SIZE and not isinstance(widget, (SelectMultiple, RadioSelect))
Expand Down Expand Up @@ -491,6 +492,16 @@ def render(self):
field=field,
)

if self.is_form_control_widget():
addon_before = (
format_html('<span class="input-group-text">{}</span>', self.addon_before) if self.addon_before else ""
)
addon_after = (
format_html('<span class="input-group-text">{}</span>', self.addon_after) if self.addon_after else ""
)
if addon_before or addon_after:
field = format_html('<div class="input-group mb-3">{}{}{}</div>', addon_before, field, addon_after)

field_with_help_and_errors = format_html("{}{}{}", field, self.get_help_html(), self.get_errors_html())
if self.is_horizontal:
field_with_help_and_errors = format_html(
Expand Down
19 changes: 19 additions & 0 deletions tests/test_bootstrap_field_input_text.py
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,25 @@ class TextTestForm(forms.Form):
self._html_default("text"),
)

addon_html = (
'<div class="django_bootstrap5-req mb-3">'
'<label for="id_test" class="form-label">Test</label>'
'<div class="input-group mb-3">'
'<span class="input-group-text">foo</span>'
'<input class="form-control" id="id_test" name="test" placeholder="Test" required type="text">'
"</div>"
"</div>"
)

self.assertHTMLEqual(
self.render('{% bootstrap_field form.test addon_before="foo" %}', context={"form": form}), addon_html
)

self.assertHTMLEqual(
self.render('{% bootstrap_field form.test addon_before="foo" layout="floating" %}', context={"form": form}),
addon_html,
)

self.assertHTMLEqual(
self.render("{% bootstrap_field form.test layout='horizontal' %}", context={"form": form}),
self._html_horizontal("text"),
Expand Down

0 comments on commit 287cc3e

Please sign in to comment.