How do I use param.Action in panel?

I want to press the “random” button and trigger view with a random value.

import param
import numpy as np
import panel as pn
import holoviews as hv

class TestPanel(param.Parameterized):
    value = param.Integer(default=3)
    random = param.Action()

    def generate_random(self):
        self.view(value=int(np.random.rand(1) * 10))
    def view(self, value=None):
        if value is None:
            value = self.value
        return hv.Curve([0, 1, 2, value])

test_panel = TestPanel()
pn.Column(test_panel.view, test_panel.param)

Also is there a method to replace self.value’s value manually?


Essentially, I want the equivalent of this with a Param class:

def plot(value):
    holoviews.object = hv.Curve([0, 1, 2, value])

def update_random(event):
    spinner.value = int(np.random.rand(1) * 10)

def update_spinner(event):
    return plot(

holoviews = pn.pane.HoloViews(hv.Curve([0, 1, 2, 3]))

spinner = pn.widgets.Spinner(name='Value', value=3), 'value')

button = pn.widgets.Button(name='Random'), 'clicks')

pn.Column(holoviews, spinner, button)


Hi @ahuang11

Something like the below should do the trick

import holoviews as hv
import numpy as np
import panel as pn
import param

DEFAULT_PLAT = hv.Curve([0,1,2,3])

class App(param.Parameterized):
    value = param.Integer(default=3)
    set_random_value = param.Action(label="Random")

    settings_pane = param.Parameter()
    plot_pane = param.Parameter()
    view = param.Parameter()

    def __init__(self, **params):

        self.set_random_value = self._set_random_value
        self.settings_pane = pn.Param(self, parameters=["value", "set_random_value"])
        self.plot_pane = pn.pane.HoloViews(DEFAULT_PLAT)
        self.view = pn.Column(self.plot_pane, self.settings_pane)

    @param.depends("value", watch=True)
    def _update_plot_pane(self):
        self.plot_pane.object = hv.Curve([0,1,2,self.value])

    def _set_random_value(self, event):
        self.value = int(np.random.rand(1) * 10)

1 Like


Hi @Marc, This implementation works great, but recently it failed in combination with a pn.widgets.FileDownload !

Having two or more param.Action() buttons with your implementation in combination with a pn.widgets.FileDownload() and the notebook crashes when trying to display the filedownload widget. Weird, I know. See first gif.

The following implementation works (better) for me. See second gif. @philippjfr, any thoughts?

    def __init__(self,**params):
        self.button = param.Action(lambda x:x.do_something_button)

    def do_something_button(self):
        print('Dummy print button')

param_Action_crashes_FileDownload_in_param.ipynb (2.8 MB)

Hi @jmccreight

I think you are experiencing the infinite Parameterized.__repr__ recursion issue.

When you have more than one action on a param.Parameterized object an infinite recursion can be triggered. This is caused by the __repr__ function. The implication of this is that your app will crash without any useful information. And you waste a a lot of time figuring this out. Or you just leave Panel behind.

I’ve really tried to communicate that this is a fundamental problem for param and Panel. But so far without luck. See Please upvote if you think this is important to get solved.

You can solve the infinite recursion problem by overriding the __repr__ method.

Ok, glad to hear it has occured before, because I did struggle to understand it. Not fully clear why my alternative instantiation of the param.Action() is not triggering infinite recursion and crashing the notebook.

I now discovered other notebook crashes (which annoyed me before) are also related to multiple param.Action objects and appear when I return a parameterized object anywhere in the notebook.see gif. However the same workaround with direct instantiation with callback resolves it.

param_Actions_cause_notebook_crash.ipynb (4.0 KB)

I hope reporting my work can help developers better understand the issues. And by the way, I’m not @jmccreight


Thanks :slight_smile: