Open maximlt opened 11 months ago
I came to write a separate Feature Request for .watch
functionality for Reactive Expressions.
Looking at https://param.holoviz.org/user_guide/Reactive_Expressions.html its not clear to me how I can use reactive expressions to trigger side effects.
I think param.watch
could and should cover reactive expressions too.
param.watch(some_function, some_parameter, some_reactive_expression)
Reactive functions actually have the .watch
method as below.
import panel as pn
pn.extension()
is_stopped=pn.rx(True)
def name(stopped):
if stopped:
return "Start the wind turbine"
else:
return "Stop the wind turbine"
rx_name = pn.rx(name)(is_stopped)
submit = pn.widgets.Button(name=rx_name)
def start_stop_wind_turbine(clicked):
print("running action")
is_stopped.rx.value = not is_stopped.rx.value
b_stop_wind_turbine = submit.rx.watch(start_stop_wind_turbine)
pn.Column(submit, b_stop_wind_turbine).servable()
I've long been thinking that it'd be nice for Param to have a
param.watch
function and decorator and finally decided it was time to write this down. I'm going to completely ignore any implementation discussion for now and whether what I'm asking for can actually be implemented. My two main asks forparam.watch
are:param.watch
function, a laobj.param.watch
@param.depends(..., watch=True)
with a decorator@param.watch(...)
being able to register side-effecty callbacks with a top-level
param.watch
function, a laobj.param.watch
Registering side-effecty callbacks outside of the scope of the Parameterized class can currently be done using
@pn.depends(..., watch=True)
or withpn.bind(func, ..., watch=True)
. In the Panel world we've been moving away from suggesting using@param.depends
in favor ofpn.bind
. However, I feel that whilepn.bind
is a great API on its own that is easy to understand as modeled onfunctools.partial
,pn.bind
together withwatch=True
changes the nature of the API in an unexpected and hard to understand way.watch
being a parameter ofpn.bind
also pollutes it. On the other hand in the context of a Parameterized class the low-levelobj.param.watch
is available and allows for the fine-grained control you sometimes need when dealing with callbacks, e.g. comparing the new and old values of a parameter, doing something when the value is set even if it's not changed.I have observed there are somehow three callback signatures I wish I could use when creating a callback:
@param.depends
decorator works currently by calling the callback only with the new valuesEvent
objects passed to the callback as I want to inspect them furtherobj.param.watch
is modeled on 3) which is the most powerful approach but also the one that requires the most code to handle the payload specially when you're watching more than one parameters, it's also more difficult to write tests for these callbacks:It'd be great if I could declare with
param.watch
what payload I'd like to get. I'm guessing the default could be 2) instead of 3) as being the more common case.The other features of
obj.param.watch
(what, onlychanged, precedence, unwatch, etc.) would certainly also be appropriate forparam.watch
.Using
param.watch
would look like:in the scope of a Parameterized class being able to replace
@param.depends(..., watch=True)
with a decorator@param.watch(...)
@param.depends()
being only declarative by default certainly causes confusion (for me at least when I got started), it's a bit strange that decorating a callback with a set of parameters to depend on isn't enough for the callback to be called on their changes. Of course this all makes sense when you realize this declaration is to be used by a library like Panel to set up its own update mechanisms. If you use Param on its own, that's definitely a weird default.I can't count how many times I have forgotten to add
watch=True
and I have at least one large app in which every@param.depends
decorator needs to havewatch=True
.For all these reasons I'm interested in a more explicit
param.watch
decorator to be used in the scope of a Parameterized class. I think what I suggested above with the ability to select the signature/payload mode could also be nice to have.