forms: use a template to render checkboxes widget (#48387)

This commit is contained in:
Frédéric Péters 2020-11-29 15:06:22 +01:00
parent 0806a631fd
commit fd09a2f6de
3 changed files with 47 additions and 67 deletions

View File

@ -928,7 +928,8 @@ class WorkflowVariablesFieldDefPage(FieldDefPage):
)
display_locations = form.get_widget('display_locations')
if display_locations:
del display_locations.widgets[0] # validation page
# remove validation page from choices
display_locations.options = display_locations.options[1:]
return form
@ -941,7 +942,8 @@ class WorkflowBackofficeFieldDefPage(FieldDefPage):
form.remove('prefill')
display_locations = form.get_widget('display_locations')
if display_locations:
del display_locations.widgets[0] # validation page
# remove validation page from choices
display_locations.options = display_locations.options[1:]
return form

View File

@ -1449,60 +1449,52 @@ class RegexStringWidget(StringWidget):
self.value = None
class CheckboxesWidget(CompositeWidget):
class CheckboxesWidget(Widget):
readonly = False
template_name = 'qommon/forms/widgets/checkboxes.html'
has_inside_labels = True
def __init__(self, name, value=None, options=None, **kwargs):
CompositeWidget.__init__(self, name, value, **kwargs)
self.element_names = collections.OrderedDict()
self.options = options
self.options_with_attributes = kwargs.pop('options_with_attributes', None)
self.inline = kwargs.pop('inline', True)
self.min_choices = int(kwargs.pop('min_choices', 0) or 0)
self.max_choices = int(kwargs.pop('max_choices', 0) or 0)
if 'title' in kwargs:
del kwargs['title']
if 'readonly' in kwargs:
del kwargs['readonly']
self.readonly = True
self.inline = kwargs.get('inline', True)
self.min_choices = int(kwargs.get('min_choices', 0) or 0)
self.max_choices = int(kwargs.get('max_choices', 0) or 0)
super().__init__(name, value, **kwargs)
self.options_with_attributes = kwargs.pop('options_with_attributes', None)
self.disabled_options = []
if self.options_with_attributes:
options = self.options_with_attributes
def is_selected(self, value):
return bool(self.value and value in self.value)
def get_options(self):
options = self.options_with_attributes or self.options
for i, option in enumerate(options):
if len(option) == 2:
key, title = option[:2]
name = 'element%d' % i
obj, description, key = (option[0], option[1], str(i))
else:
_, title, key = option[:3]
name = 'element%s' % str(key)
key = str(key)
element_kwargs = kwargs.copy()
if self.options_with_attributes and option[-1].get('disabled'):
element_kwargs['disabled'] = 'disabled'
self.disabled_options.append(name)
# don't mark individual checkboxes as required
element_kwargs.pop('required', None)
checked = bool(value and key in value)
self.add(CheckboxWidget, name, title=title, value=checked, **element_kwargs)
self.element_names[name] = key
obj, description, key = option[:3]
yield {
'name': self.name + '$element%s' % key,
'value': obj,
'label': description,
'disabled': bool(self.options_with_attributes and option[-1].get('disabled')),
'selected': self.is_selected(obj),
}
def _parse(self, request):
if self.readonly:
return
values = []
for name in self.element_names:
if name in self.disabled_options:
for option in self.get_options():
if option.get('disabled'):
continue
value = self.get(name)
if value is True:
values.append(self.element_names[name])
name = option['name']
if name in request.form and not request.form[name] in (False, '', 'False'):
values.append(option['value'])
self.value = values
if self.required and not self.value:
self.set_error(self.REQUIRED_ERROR)
@ -1513,40 +1505,8 @@ class CheckboxesWidget(CompositeWidget):
def set_value(self, value):
self.value = value
for name in self.element_names:
widget = self.get_widget(name)
if self.element_names[name] in self.value:
widget.set_value(True)
else:
widget.set_value(False)
self._parsed = True
def has_error(self, request=None):
return Widget.has_error(self, request=request)
def render_content(self):
r = TemplateIO(html=True)
if self.inline:
r += htmltext('<ul class="inline">')
else:
r += htmltext('<ul>')
for widget in self.get_widgets():
if widget.attrs and 'disabled' in widget.attrs:
r += htmltext('<li class="disabled"><label>')
else:
r += htmltext('<li><label>')
if self.readonly:
widget.attrs['disabled'] = 'disabled'
if widget.value:
r += htmltext('<input type="hidden" name="%s" value="yes" >') % widget.name
widget.name = widget.name + 'xx'
r += widget.render_content(standalone=False)
r += htmltext('<span>%s</span>') % widget.title
r += htmltext('</label>')
r += htmltext('</li>')
r += htmltext('</ul>')
return r.getvalue()
class ValidatedStringWidget(StringWidget):
'''StringWidget which checks the value entered is correct according to a regex'''

View File

@ -0,0 +1,18 @@
{% extends "qommon/forms/widget.html" %}
{% block widget-control %}
<ul {% if widget.inline %}class="inline"{% endif %}>
{% for option in widget.get_options %}
<li {% if option.disabled %}class="disabled"{% endif %}><label><input
{% if option.selected %}checked="checked"
{% elif widget.readonly or option.disabled %}disabled{% endif %}
{% for attr in widget.attrs.items %}{{attr.0}}="{{attr.1}}"{% endfor %}
type="checkbox"
{% if widget.readonly %}value="yes" disabled
{% else %}name="{{ option.name }}" value="yes">
{% endif %}<span>{{ option.label }}</span></label>
{% if widget.readonly and option.selected %}<input type="hidden" name="{{ option.name }}" value="yes">{% endif %}
</li>
{% endfor %}
</ul>
{% endblock %}