How to check if button is clicked for param.Action

Hello guys,
I have a param.Action button created to trigger a run when it’s clicked. I’m wondering if there’s a way to check if the button is clicked ? kind of similar to ‘on_click’ event of button widget. Thanks!

button = param.Action(default=lambda x: x.param.trigger('button'), label='Run!') 

Hi, Not sure what the use-case would be for checking the button click separately.

Basically for a Button you want to usually perform an action when the button is clicked. There are different ways to do it. But in essence you’re usually registering a function/method that gets called immediately when the button gets clicked.

Here an example with 3 different methods:

  • option 1 & 2 use the param.Parameterized + param.Action to allow automatically generate widgets and use param/panel convenience to link to the callback function/method.
  • option 3 is the classic defining a widget separately and linking a call-back function direclty.

The main difference between option 1 and option 2 is that with option 1 you can in theory have and trigger multiple dependencies, but in reality you likely need to actually trigger a sequence of steps in a specific order anyway, so use a single function to execute the work that needs to be done. Also you could still also trigger multiple dependencies on option 2, by adding a dependency to when the actual function gets executed (triggering more

import param
import panel as pn

class Test(param.Parameterized):

    # option 1: define an action that triggers itself. 
    # - you can use panel pn.Param or pn.widgets.Button.from_param() to create a Button automatically
    # - once the button is hit the param.Parameterized class will execute anything 
    #   that depends on that parameter via @param.depends or triggers any defined "watcher" for this parameter
    abort = param.Action(default=lambda x: x.param.trigger('abort'))

    # option 2: define an action that just directly calls the function/method
    # - you can use panel pn.Param or pn.widgets.Button.from_param() to create a Button automatically
    # - once the button is hit, the registered function/method will be directly executed
    #   (no extra @param.depends necessary)
    save = param.Action(default=lambda self: self.save_data())

    @param.depends('abort', watch=True)
    def abort_change(self, **kwargs):
        print(f'abort_change(self={self}, kwargs={kwargs})')
    def save_data(self, **kwargs):
        print(f'save_data(self={self}, kwargs={kwargs})')

    # option 3: manually create a button widget and register a function via button.on_click()
    # - you need to manually create the button, it will have *no* direct connection to the parameterized class
    # - on button click the widget will call the registered callback function/method
    def delete_button(self):
        button = pn.widgets.Button(name='Delete')
        return button
    def delete_data(self, event, **kwargs):
        print(f'delete_data(self={self}, event={event}, kwargs={kwargs})')

test = Test()

pn.Column(pn.Param(test.param), test.delete_button())    

Not sure if that addresses your actual use-case or if you really need to do something very special.
Regards, Johann

1 Like

Hey Johann,

Thanks for your reply. For my use case, the param.action is used to trigger a method to run a query and pull data from a database. So the subsequent steps depend on the data pull results. Widget button has the click event that I can use to track if the button is clicked so I can run the follow up process. However, param.action doesn’t have the click event. So I found this pn.state.param.busy Boolean value might seem to be useful for my use case. The only problem now is how to make the param.Action button click only one time so databse query only execute one time? Appreciate your help again!


Already wrapped up,traveling tomorrow. So just some thoughts.

To trigger any subsequent work externally after the button action is done you could try one of the 2 methods:

  1. Store the action dB query result in a output param.parameter and put a @param.depends on it
    2.put a @param.depends on the action callback method/function
1 Like