form: use subclass of BoundFormField that overrides is_in_error

Instead of using isinstance(self.widget, SubFormWidget) in
BoundFormField.is_in_error, we now implement a BoundSubFormField
class that inherits from BoundFormField. It is meant to be instantianted
for subforms fields only.

This class overrides is_in_error() to perform the additional checks in
the forms' sub-fields.

Signed-off-by: Olivier Gayot <olivier.gayot@canonical.com>
This commit is contained in:
Olivier Gayot 2022-06-09 09:54:18 +02:00
parent 10192e9b74
commit c72e7eec87
1 changed files with 40 additions and 32 deletions

View File

@ -111,27 +111,6 @@ class _Validator(WidgetWrap):
self.field.validate() self.field.validate()
class FormField(abc.ABC):
next_index = 0
takes_default_style = True
caption_first = True
def __init__(self, caption=None, help=None):
self.caption = caption
self.help = help
self.index = FormField.next_index
FormField.next_index += 1
@abc.abstractmethod
def _make_widget(self, form):
pass
def bind(self, form):
widget = self._make_widget(form)
return BoundFormField(self, form, widget)
class WantsToKnowFormField(object): class WantsToKnowFormField(object):
"""A marker class.""" """A marker class."""
def set_bound_form_field(self, bff): def set_bound_form_field(self, bff):
@ -161,16 +140,8 @@ class BoundFormField(object):
widget.set_bound_form_field(self) widget.set_bound_form_field(self)
def is_in_error(self) -> bool: def is_in_error(self) -> bool:
""" Tells whether this field is in error. We will also check if any of """ Tells whether this field is in error. """
the enabled subform reports an error. return self.in_error
"""
if self.in_error:
return True
if not self._enabled or not isinstance(self.widget, SubFormWidget):
return False
return self.widget.form.has_validation_error()
def _build_table(self): def _build_table(self):
widget = self.widget widget = self.widget
@ -310,6 +281,42 @@ class BoundFormField(object):
row.enabled = val row.enabled = val
class BoundSubFormField(BoundFormField):
def is_in_error(self):
""" Tells whether this field is in error. We will also check if the
subform (if enabled) reports an error.
"""
if super().is_in_error():
return True
if not self._enabled:
return False
return self.widget.form.has_validation_error()
class FormField(abc.ABC):
next_index = 0
takes_default_style = True
caption_first = True
bound_field_class = BoundFormField
def __init__(self, caption=None, help=None):
self.caption = caption
self.help = help
self.index = FormField.next_index
FormField.next_index += 1
@abc.abstractmethod
def _make_widget(self, form):
pass
def bind(self, form):
widget = self._make_widget(form)
return self.bound_field_class(self, form, widget)
def simple_field(widget_maker): def simple_field(widget_maker):
class Field(FormField): class Field(FormField):
def _make_widget(self, form): def _make_widget(self, form):
@ -517,7 +524,7 @@ class Form(object, metaclass=MetaForm):
narrow_rows=narrow_rows) narrow_rows=narrow_rows)
def has_validation_error(self) -> bool: def has_validation_error(self) -> bool:
""" Tells if any field (or subformfield) is in error. """ """ Tells if any field is in error. """
return any(map(lambda f: f.is_in_error(), self._fields)) return any(map(lambda f: f.is_in_error(), self._fields))
def validated(self): def validated(self):
@ -554,6 +561,7 @@ class SubFormWidget(WidgetWrap):
class SubFormField(FormField): class SubFormField(FormField):
takes_default_style = False takes_default_style = False
bound_field_class = BoundSubFormField
def __init__(self, form_cls, caption=None, help=None): def __init__(self, form_cls, caption=None, help=None):
super().__init__(caption=caption, help=help) super().__init__(caption=caption, help=help)