Skip to content

Commit 2b9213a

Browse files
committed
extend Button widget to use rendering size
1 parent 158969d commit 2b9213a

File tree

5 files changed

+52
-9
lines changed

5 files changed

+52
-9
lines changed

formset/renderers/__init__.py

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -63,3 +63,8 @@ class ButtonVariant(StrEnum):
6363
DANGER = auto()
6464
WARNING = auto()
6565
INFO = auto()
66+
67+
68+
class ButtonSize(StrEnum):
69+
SMALL = auto()
70+
LARGE = auto()

formset/renderers/admin.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -49,6 +49,7 @@ def _amend_button(self, context):
4949
elif context['widget']['variant'] == ButtonVariant.PRIMARY:
5050
class_list.add('primary')
5151
context['widget']['attrs']['class'] = class_list
52+
context['icon_class'] = ' me-1' if context['icon_left'] else ' ms-1'
5253
return context
5354

5455
_context_modifiers = dict(DefaultFormRenderer._context_modifiers, **{

formset/renderers/bootstrap.py

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
from django.utils.html import format_html
22

3-
from formset.renderers import ButtonVariant, ClassList
3+
from formset.renderers import ButtonSize, ButtonVariant, ClassList
44
from formset.renderers.default import FormRenderer as DefaultFormRenderer
55

66

@@ -39,13 +39,18 @@ def _amend_select(self, context):
3939
return context
4040

4141
def _amend_button(self, context):
42+
class_list = ClassList(context['widget']['attrs'].get('class'))
4243
variant = context['widget']['variant']
4344
if not isinstance(variant, ButtonVariant):
4445
variant = 'outline-secondary'
45-
class_list = ClassList(context['widget']['attrs'].get('class'))
4646
class_list.add(f'btn btn-{variant}')
47+
size = context['widget']['size']
48+
if size is ButtonSize.SMALL:
49+
class_list.add('btn-sm')
50+
elif size is ButtonSize.LARGE:
51+
class_list.add('btn-lg')
4752
context['widget']['attrs']['class'] = class_list
48-
context['icon_class'] = ' me-3' if context['icon_left'] else ' ms-3'
53+
context['icon_class'] = ' me-1' if context['icon_left'] else ' ms-1'
4954
return context
5055

5156
def _amend_dual_selector(self, context):

formset/renderers/tailwind.py

Lines changed: 15 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
from formset.boundfield import ClassList
2+
from formset.renderers import ButtonSize, ButtonVariant, ClassList
23
from formset.renderers.default import FormRenderer as DefaultFormRenderer
34

45

@@ -86,7 +87,20 @@ def _amend_radio(self, context):
8687
return self._amend_multiple_input(context, 'formset-radio-select')
8788

8889
def _amend_button(self, context):
89-
context['widget']['attrs']['class'] = ClassList('formset-button-default')
90+
class_list = ClassList(context['widget']['attrs'].get('class'))
91+
variant = context['widget']['variant']
92+
if not isinstance(variant, ButtonVariant):
93+
variant = 'default'
94+
class_list.add(f'formset-button-{variant}')
95+
size = context['widget']['size']
96+
if size is ButtonSize.SMALL:
97+
class_list.add('formset-button-small')
98+
elif size is ButtonSize.LARGE:
99+
class_list.add('formset-button-large')
100+
else:
101+
class_list.add('formset-button-base')
102+
context['widget']['attrs']['class'] = class_list
103+
context['icon_class'] = ' me-1' if context['icon_left'] else ' ms-1'
90104
return context
91105

92106
def _amend_fieldset(self, context):

formset/widgets/button.py

Lines changed: 23 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
from django.forms.widgets import Widget
2-
from django.template.loader import get_template
2+
from django.template.loader import get_template, render_to_string
33
from django.utils.functional import cached_property
44

55

@@ -8,25 +8,37 @@ class Button(Widget):
88
button_type = 'button'
99
action = None
1010
button_variant = None
11+
button_size = None
1112
icon_path = None
13+
icon_char = None
1214
icon_left = None
1315

1416
def __init__(
1517
self,
1618
attrs=None,
1719
action=None,
1820
button_variant=None,
21+
button_size=None,
1922
auto_disable=False,
23+
omit_restore=False,
2024
icon_path=None,
25+
icon_char=None,
2126
icon_left=False
2227
):
2328
if action is not None:
2429
self.action = action
2530
if button_variant:
2631
self.button_variant = button_variant
32+
if button_size:
33+
self.button_size = button_size
2734
self.auto_disable = auto_disable
35+
self.omit_restore = omit_restore
36+
if icon_path and icon_char:
37+
raise ValueError("Specify either icon_path or icon_char, not both.")
2838
if icon_path:
2939
self.icon_path = icon_path
40+
if icon_char:
41+
self.icon_char = icon_char
3042
self.icon_left = icon_left
3143
super().__init__(attrs)
3244

@@ -36,20 +48,26 @@ def build_attrs(self, base_attrs, extra_attrs=None):
3648
attrs['df-click'] = self.action
3749
if self.auto_disable:
3850
attrs['auto-disable'] = True
51+
if self.omit_restore:
52+
attrs['omit-restore'] = True
3953
return attrs
4054

4155
def get_context(self, name, value, attrs):
4256
context = super().get_context(name, value, attrs)
4357
context['label'] = context['widget']['attrs'].pop('label', None) # for buttons, the label is the value
4458
context['widget']['type'] = self.button_type
4559
context['widget']['variant'] = self.button_variant
60+
context['widget']['size'] = self.button_size
4661
context['icon_element'] = self.icon_element
4762
context['icon_left'] = self.icon_left
4863
return context
4964

5065
@cached_property
5166
def icon_element(self):
52-
if self.icon_path:
53-
template = get_template(self.icon_path)
54-
return template.render()
55-
return ''
67+
if self.icon_char:
68+
icon = self.icon_char
69+
elif self.icon_path:
70+
icon = render_to_string(self.icon_path)
71+
else:
72+
return ''
73+
return icon

0 commit comments

Comments
 (0)