holoviz / panel

Panel: The powerful data exploration & web app framework for Python
https://panel.holoviz.org
BSD 3-Clause "New" or "Revised" License
4.74k stars 516 forks source link

Cannot set object parameter of Plotly pane to bound function after construction #5141

Open MarcSkovMadsen opened 1 year ago

MarcSkovMadsen commented 1 year ago

I'm trying to help a user on discourse who wants his Plotly plot to depend on his selections/ clicks on the plot. See https://discourse.holoviz.org/t/updating-a-selectbox-dependent-plotly-scatterplot-based-on-click-events/5542

If figured I could do that by first creating the widgets and Plotly pane. Then bind the function that creates the figure to these. Finally I could set the object on the Plotly pane.

But that seems not possible. I get ValueError: Invalid element(s) received for the 'data' property of Invalid elements include: [<function _param_bind..wrapped at 0x000001C4B56B4DC0>]

import panel as pn

import plotly.express as px
import pandas as pd

pn.extension("plotly", sizing_mode="stretch_width")

data = pd.DataFrame({
    'Stat1': [5, 8, 3, 6],
    'Stat2': [7, 10, 4, 8],
    'Stat3': [9, 12, 6, 10],
    'Stat4': [4, 6, 2, 5]
})

def get_plot(graph_option1, graph_option2, click_data, data=data):
    fig = px.bar(data, x=graph_option1, y=graph_option2, title=f'{graph_option1}, {graph_option2}')
    fig.layout.autosize=True
    return fig

graph_options = list(data)
graph_option1 = pn.widgets.Select(name="x-axis Stat:", 
                options=graph_options, value="Stat1")
graph_option2 = pn.widgets.Select(name="y-axis Stat:", 
                options=graph_options, value="Stat2")

plot_pane = pn.pane.Plotly()

bound_plot = pn.bind(get_plot, graph_option1=graph_option1, graph_option2=graph_option2, click_data=plot_pane.param.click_data)

plot_pane.object=bound_plot

pn.template.FastListTemplate(
    title="Reacting to Plotly events",
    sidebar=[graph_option1, graph_option2],
    main=[plot_pane]
).servable()

image

philippjfr commented 1 year ago

Currently you cannot set any parameter to a reference after construction, currently this is only supported in the constructor.

philippjfr commented 1 year ago

I'd maybe suggest closing this issue and creating a general feature request for this. It's on my to-do list already but I haven't created an issue for it yet.