How to disable/enable a button based status from other widgets

Hi,

Is there a way to disable/enable a button based on the status from another widget (either composite or a completely different one in memory)? For example:

class Subapp(param.Parameterized):
    status = param.Boolean(default=False)
    
    def panel(self):
        self.checkbox = pn.widgets.Checkbox.from_param(self.param.status)
        return self.checkbox

class Mainapp(param.Parameterized):
    subapp = Subapp()
    action = param.Action(lambda x: x.param.trigger("action"))
    
    @param.depends("action", watch=True)
    def perform_action(self):
        print("yes")

    def panel(self):
        action_btn = pn.widgets.Button.from_param(
            self.param.action,
            disabled=not self.subapp.status,
        )   
        app = pn.Row(self.subapp.panel, action_btn)
        return app

The hope here is that the boolean status from the subapp can be link to the button in the main app.
Currently, the button is disabled by default, and changing the status does not update the button status.

There are many, many ways to do this. This is one

The key is this part

@param.depends("subapp.status")
def action_btn(self):
      return pn.widgets.Button.from_param(
            self.param.action,
            disabled=not self.subapp.status,
        )

The full app is

import panel as pn
import param

pn.extension()

class SubApp(pn.viewable.Viewer):
    status = param.Boolean(default=False)
    
    def __init__(self, status: bool=False, **params):
        super().__init__(status=status)

        self._panel = pn.widgets.Checkbox.from_param(self.param.status, **params)
    
    def __panel__(self):
        return self._panel

class MainApp(pn.viewable.Viewer):
    subapp = param.ClassSelector(class_=SubApp)
    action = param.Event()
    clicks = param.Integer()

    def __init__(self, **params):
        if not "subapp" in params:
            params["subapp"]=SubApp()
        
        super().__init__(**params)

        self._panel = pn.Column(self.subapp, self.action_btn, self.param.clicks)
    
    @param.depends("action", watch=True)
    def perform_action(self):
        self.clicks += 1

    @param.depends("subapp.status")
    def action_btn(self):
        return pn.widgets.Button.from_param(
            self.param.action,
            disabled=not self.subapp.status,
        )

    def __panel__(self):
        return self._panel

MainApp().servable()

1 Like

This is exactly what I have in mind. Thanks :grin:

1 Like