How to add an on_click event to Parameterized dataframe widget?

Hi. I’d like to control some figures using a dataframe for source options. After a bit of exploration I came to the following snippet below (for demo purposes). I’m not entirely happy using the private attribute param._widgets to add the on_click event. Is there an alternative?

import numpy as np
import pandas as pd
import panel as pn
import param
import plotly.express as px

pn.extension("plotly", "tabulator")

def get_options_df():
    return pd.DataFrame(
        {
            "name": ["beta", "normal", "lognormal"],
            "params": ["1, 1, 10000", "0, 1, 10000", "1, 1, 10000"],
        }
    )


class HistogramParam(param.Parameterized):
    options = param.DataFrame(default=get_options_df())
    selected = param.Series(default=get_options_df().iloc[0], precedence=-1)

    def table_click(self, event):
        self.selected = self.options.iloc[event.row]

    @param.depends("selected")
    def histogram_chart(self):
        s = self.selected
        data = eval(f"np.random.{s['name']}({s['params']})")
        fig = px.histogram(data)
        fig.update_layout(autosize=True)
        return fig

    def view(self):
        param = pn.Param(self.param)
        param._widgets["options"].on_click(self.table_click)
        return param

params = HistogramParam()
pn.Column(params.view(), params.histogram_chart, height=600)

There is no need to use pn.Param to turn the only parameter you have into a widget (pn.Param basically creates widgets out of the parameters of a param.Parameterized class and a container to host them).

You can just create the widget manually

    def view(self):
        w_df = pn.widgets.Tabulator.from_param(self.param.options)
        w_df.on_click(self.table_click)

        return w_df

I’m not sure though if having our various options in a DF is the right thing (usually you’d go with a param.Selector()). But it may make sense if your use case is to display all possible options (incl. the parameters) in a a concise tightly packed list.

There are different ways, the post below has a nice summary and some discussion:

You should assume I’ve simplified my snippet for the sake of asking this question. I’m actually using more than one widget.