Hi All
I’m quite new to panel and param and really like them. I’m trying to build an app that will be based on a moderately complicated data model, which I’m building in parameterized classes. These classes will sometimes be nested at various levels, but they should work independently too. This seems to be to be a very natural use case. I’ve expressed it quite abstractly, but for instance, if you have a Recipe object, it might have a list of Ingredient objects, and you might want to be able to handle each of those classes independently of the other some time. I like the declarative nature of param for this kind of task because it means you can declare the relationships between the data/classes and worry about displaying it or not when it comes to the UI.
So to pursue that example, if you’ve got a visualisation based on a Recipe (maybe showing downloads, reviews stats, etc) it could incorporate a tab or pane for focusing on an ingredient. Then the user might select an ingredient using a dropdown (i.e. Selector) and then the relevant pane/panes would update to show the stats for that ingredient.
So my question is how to get the reference to the selected instance in such a way that it can be used as the object that’s visualised in the relevant pane/s.
Displaying the following in panel works as I want (sticking with the Recipe case): recipe_instance.param — this displays the Selector object with a blue button and the button reveals the instance currently selected with it’s parameterized properties, which can be changed and which persist if you chance the instance using the Selector then change it back.
This is the functionality I want but I don’t want to be limited to displaying everything automatically in one place as with recipe_instance.param. I want to put the Selector in one place (e.g. sidebar) and the inner class parameters in another place (panes or tabs).
Here is a minimal example to show what I mean and some of the ways I would intuitively think it could be achieved. None of these work. They display the instance of the inner class that is the value of the Selector when the outer class is initiated, but they do not update to another instance if the value of the Selector is changed.
I would be extremely grateful for any pointers—perhaps there’s an obvious way to do this that I’m missing.
import panel as pn
import param
class Inner(param.Parameterized):
target_param = param.String(default="default")
dependent_param = param.String(constant=True)
@param.depends('target_param', watch=True)
def _update_dependent_param(self):
with param.edit_constant(self):
self.dependent_param = self.target_param
inner1 = Inner(target_param="inner1 parameter")
inner2 = Inner(target_param="inner2 parameter")
inner_objs = [inner1, inner2]
class Outer(param.Parameterized):
instance_of_Inner = param.Selector(default=inner_objs[0],
objects=inner_objs)
outer = Outer()
references = {
'(1) outer.param.instance_of_Inner \n\n this is the Selector object that will choose which instance of class Inner is active' : outer.param.instance_of_Inner,
'(2) outer.instance_of_Inner \n\n this is the value of that Selector object (an instance of Inner) and I would expect it not to update' : outer.instance_of_Inner,
'(3) outer.instance_of_Inner.param \n\n this should be the instance as a Parameterized object, I would expect this to change reflecting changes in the selection made with the Selector' : outer.instance_of_Inner.param,
'(4) outer.param \n\n for good measure, to see what calling the Outer as a param object does': outer.param,
'(5) outer \n\n for good measure, to see what calling the Outer as a value object does': outer,
}
panes = [pn.Column(k, references[k]) for k in references.keys()]
print(panes)
pn.Column(*panes).servable()