Document how to use .from_param to create a widget from a reactive parameter
I can't figure out how to create a widget from a reactive parameter.
More specifically
import panel as pn
pn.extension()
zoom = pn.rx(2)
slider = pn.widgets.IntSlider.from_param(zoom, start=1, end=10)
I get
AttributeError: 'rx' object has no attribute 'name'
Traceback (most recent call last):
File "/home/jovyan/repos/private/panel-geospatial/.venv/lib/python3.11/site-packages/panel/io/handlers.py", line 389, in run
exec(self._code, module.__dict__)
File "/home/jovyan/repos/private/panel-geospatial/pages/03_mapbox.py", line 11, in <module>
pn.widgets.IntSlider.from_param(zoom, start=1, end=10)
File "/home/jovyan/repos/private/panel-geospatial/.venv/lib/python3.11/site-packages/panel/widgets/base.py", line 93, in from_param
parameter, widgets={parameter.name: dict(type=cls, **params)},
^^^^^^^^^^^^^^
File "/home/jovyan/repos/private/panel-geospatial/.venv/lib/python3.11/site-packages/param/reactive.py", line 1032, in __getattribute__
return super().__getattribute__(name)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
AttributeError: 'rx' object has no attribute 'name'
I cannot find this documented anywhere.
A workaround would be to define the widget first and the from it the reactive parameter. But the problem is that then I cannot update the value of the reactive parameter
AttributeError: Setting the value of a reactive expression is only supported if it wraps a concrete value. A reactive expression wrapping a Parameter or another dynamic reference cannot be updated.
I believe it should be possible to update it.
import panel as pn
pn.extension()
zoom_input = pn.widgets.IntSlider(value=2, start=1, end=10, name="Zoom")
zoom = zoom_input.rx()
zoom.rx.value=3
This does not work either
import panel as pn
pn.extension()
zoom = pn.rx(2)
zoom_input = pn.widgets.FloatSlider(value=zoom, start=1, end=10, step=1.0, name="Zoom")
zoom_input.value=3
print(zoom.rx.value)
Here the problem is that there is only one-way binding from reactive parameter to widget. Not the other way.
There is no way to reverse bind an rx expression since it isn't possible to invert arbitrary expressions.
We could add support for inverting an expression that simply mirrors a parameter value but as soon as you do something with it there's no way.
This can be achieved by this code
import panel as pn
pn.extension()
frequency = pn.rx(1)
slider = pn.widgets.FloatSlider(value=1, start=0, end=10)
def set(value):
frequency.rx.value=value
slider.rx().rx.watch(set)
pn.Column(slider, frequency).servable()
I think that is lengthy. In react you always get value, set_value where set_value is a function to update the value. I think there should be a set, set_value or update special method on .rx to make this easier.
import panel as pn
pn.extension()
frequency = pn.rx(1)
slider = pn.widgets.FloatSlider(value=1, start=0, end=10)
slider.rx().rx.watch(frequency.rx.set_value)
pn.Column(slider, frequency).servable()
Do you agree? Should I file a request with param?
Closing since this has been filed upstream: https://github.com/holoviz/param/issues/956
This issue has been automatically locked since there has not been any recent activity after it was closed. Please open a new issue for related bugs.