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
pn.extension()

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

    @param.depends('random')
    def generate_random(self):
        self.view(value=int(np.random.rand(1) * 10))
    
    @param.depends('value')
    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?

image

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(event.new)

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

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

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

pn.Column(holoviews, spinner, button)

image

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):
        super().__init__(**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)

App().view.servable()
1 Like

Thanks!!

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):
        super().__init__(**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 https://github.com/holoviz/param/issues/396. 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

2 Likes

Thanks :slight_smile: