It might also be a documentation issue rather than a bug.
The general advice here is really to set private attributes before calling init_components
.
Which is good practice in general with property getters and setters.
Think of the call to init_components
as expecting all private attributes, which are used in data bindings, to exist.
With a single attribute that’s fine because you call the setter before the getter.
But with n attributes you call some getters before the setters
(when using the refresh_data_bindings()
approach).
Both @jshaffstall suggestion and my suggestion stick to this rule of thumb
i.e. setting private attributes before calling init_components
.
@jshaffstall suggestion does this specifically for self._error
(you’d probably want to do this for self._title
too.
class LabelTextBox(LabelTextBoxTemplate):
def __init__(self, **properties):
# set private attributes used in data bindings
self._title = ""
self._error = ""
# do init_components
self.init_components(**properties)
What i’ve suggested puts all the private attributes inside self._props
before the call to self.init_components()
class LabelTextBox(LabelTextBoxTemplate):
def __init__(self, **properties):
# set private attributes used in data bindings
self._props = properties.copy()
# do init_components
self.init_components(**properties)
Both approaches are equivalent really.
Other approaches to consider depending on preference
Use a flag to avoid calling refresh_data_bindings until init_components() is done
class LabelTextBox(LabelTextBoxTemplate):
def __init__(self, **properties):
self._init = False
self.init_components(**properties)
# other code
self._init = True
@property
def title(self):
return self._title
@title.setter
def title(self, value):
self._title = value
if self._init:
self.refresh_data_bindings()
@property
def error(self):
return self._error
@error.setter
def error(self, value):
self._error = value
if self._init:
self.refresh_data_bindings()
Don't use data bindings but access the properties directly in code
class LabelTextBox(LabelTextBoxTemplate):
def __init__(self, **properties):
self.init_components(**properties)
@property
def title(self):
return self._title
@title.setter
def title(self, value):
self._title = value
self.label_title.text = value
@property
def error(self):
return self._error
@error.setter
def error(self, value):
self._error = value
self.label_error.text = value
Don't use private attributes, just use component properties
(this approach is particularly useful for a TextBox/CheckBox when the property can be changed by the user)
class LabelTextBox(LabelTextBoxTemplate):
def __init__(self, **properties):
self.init_components(**properties)
@property
def title(self):
return self.label_title.text
@title.setter
def title(self, value):
self.label_title.text = value
@property
def error(self):
return self.label_error.text
@error.setter
def error(self, value):
self.label_error.text = value