I am investigating on how to use panel with param on nested parameters and how to properly display the parameters.
Consider the minimum working example below:
import panel as pn
import param
pn.extension()
class Person(param.Parameterized):
first_name = param.String(label="First Name")
last_name = param.String(label="Last Name")
class Family(param.Parameterized):
father = param.ClassSelector(class_=Person, label="Father")
mother = param.ClassSelector(class_=Person, label="Mother")
children = param.List(item_type=Person, label="Children")
family = Family(
father=Person(first_name="John", last_name="Doe"),
mother=Person(first_name="Jane", last_name="Doe"),
children=[Person(first_name="Alice"), Person(first_name="Bob")],
)
pn.Column(pn.panel(family.param, expand_button=False, expand=True)).show()
The resulting HTML looks like this:
In pseudo style the image above βtranslatesβ to:
Family
βββ Father (cryptic line edit)
βββ Mother (cryptic line edit)
βββ Children (cryptic line edit)
βββ <Cryptic reference Father>
β βββ First name
β βββ Last name
βββ <Cryptic reference Mother>
βββ First name
βββ Last name
Is there a way to realize the following style:
Family
βββ Father (Header only)
β βββ First name
β βββ Last name
βββ Mother (Header only)
β βββ First name
β βββ Last name
βββ Child 1 (Header only)
β βββ First name
β βββ Last name
βββ Child 2 (Header only)
βββ First name
βββ Last name
Thank you in advance for any help or guidance.
1 Like
Marc
October 4, 2024, 7:17pm
2
Hi @nknavasto
Welcome to the community.
For example you can use the Viewer
base class to create custom views of your Parameterized classes:
import panel as pn
import param
pn.extension()
class Person(pn.viewable.Viewer):
first_name = param.String(label="First Name")
last_name = param.String(label="Last Name")
def __panel__(self):
return pn.Row(self.param.first_name, self.param.last_name)
class Family(pn.viewable.Viewer):
father = param.ClassSelector(class_=Person, label="Father")
mother = param.ClassSelector(class_=Person, label="Mother")
children = param.List(item_type=Person, label="Children")
def __panel__(self):
child_items = []
for item, child in enumerate(self.children):
child_items.append(f"## Child {item}")
child_items.append(child)
return pn.Column("## Father", self.father, "## Mother", self.mother, *child_items)
family = Family(
father=Person(first_name="John", last_name="Doe"),
mother=Person(first_name="Jane", last_name="Doe"),
children=[Person(first_name="Alice"), Person(first_name="Bob")],
)
pn.Column(family).servable()
1 Like
Hi Marc,
thank you very much for your answer. This helped me a lot.
1 Like
Marc
October 5, 2024, 9:35am
4
If you will update the children
dynamically you will need to do something like below
import panel as pn
import param
pn.extension()
class Person(pn.viewable.Viewer):
first_name = param.String(label="First Name")
last_name = param.String(label="Last Name")
def __panel__(self):
return pn.Row(self.param.first_name, self.param.last_name)
class Family(pn.viewable.Viewer):
father = param.ClassSelector(class_=Person, label="Father")
mother = param.ClassSelector(class_=Person, label="Mother")
children = param.List(item_type=Person, label="Children")
@pn.depends("children")
def _child_view(self):
child_items = []
for item, child in enumerate(self.children):
child_items.append(f"## Child {item}")
child_items.append(child)
return pn.Column(*child_items, margin=0)
def __panel__(self):
child_items = []
for item, child in enumerate(self.children):
child_items.append(f"## Child {item}")
child_items.append(child)
return pn.Column("## Father", self.father, "## Mother", self.mother, self._child_view)
family = Family(
father=Person(first_name="John", last_name="Doe"),
mother=Person(first_name="Jane", last_name="Doe"),
children=[Person(first_name="Alice"), Person(first_name="Bob")],
)
pn.Column(family).servable()
1 Like