I am trying to design apps with a lot of nested parameterized classes, but I ran into a confusing situation.
If one runs the following minimal app:
import param
import panel as pn
class A(param.Parameterized):
input_widget = param.ClassSelector(class_=pn.widgets.TextInput, default=pn.widgets.TextInput())
@param.depends('input_widget.value', watch=True)
def do_stuff(self):
print("Hello Panel")
def __panel__(self):
return self.input_widget
class B(param.Parameterized):
a = param.ClassSelector(class_=A, default=A())
def __panel__(self):
return self.a
pn.Column(B()).servable()
it fails to load with
AttributeError: 'TextInput' object has no attribute 'do_stuff'
This is very confusing for the user since the app just showing A works, so you’d expect it to work too if you embed A in B.
The issue seems to be related to some param copy-logic, and one way to work around this is by changing it to
class B(param.Parameterized):
a = param.ClassSelector(class_=A, default=A(), instantiate=False)
def __panel__(self):
return self.a
But i am not sure that is correct if one has multiple instances of B. Maybe one would need to pass in a value for A each time, but that seems cumbersome too.
Is this pattern of nesting widgets fundamentally wrong or is this unexpected behavior?