Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
11 changes: 7 additions & 4 deletions shinywidgets/_reactable.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,10 +4,13 @@
reactable-py's widget never calls `model.send()` itself, but its JavaScript
bundle exports R reactable's state API (`getState`/`onStateChange`), keyed by
the table's `elementId` prop (which `render_reactable` defaults to a unique
value when the user didn't set one). When an accessor attaches, the bridge in
`js/src/reactable.ts` subscribes to that API and forwards a pruned table state
(page, sort, filters, search, selection) as custom messages, so nothing is
subscribed and no traffic flows until an accessor is read.
value when the user didn't set one). Every accessor here is kind="state", so
they all attach at render: the bridge in `js/src/reactable.ts` binds once per
model, subscribing to that API and forwarding the pruned table state (page,
sort, filters, search, selection) as custom messages. The accessors share
that one subscription -- each emits only its `key` slice -- and binding is
idempotent on the JS side, so re-renders and several accessors don't stack
subscriptions.
"""

from __future__ import annotations
Expand Down
24 changes: 24 additions & 0 deletions shinywidgets/_render_widget.py
Original file line number Diff line number Diff line change
Expand Up @@ -984,6 +984,17 @@ class render_ipyleaflet(_IpyleafletAccessors, render_widget_base[ValueT, Leaflet
render function, which builds a new map each time it runs. For anything
beyond them, use :func:`~shinywidgets.reactive_read` on ``map.widget``.

``clicked()`` attaches to the map on its first read, so a click made
before that first read is lost. If the first reader runs late -- e.g. a
chat handler, or an effect gated on ``input.action_button()`` -- read it
once, unconditionally, at startup to attach it immediately:

```python
@reactive.effect
def _():
map.clicked() # attach now, so early clicks aren't lost
```

Parameters
----------
width
Expand Down Expand Up @@ -3437,6 +3448,19 @@ class render_plotly(render_widget_base[PlotlyValueT, FigureWidget]):
a new plot each time it runs. To change the plot in response to a click,
modify ``.widget`` from a ``@reactive.effect`` instead (see the example).

``clicked()``, ``selecting()``, ``brushing()``, and ``relayout()`` attach
to the plot on their first read, so a gesture made before that first read
is lost (``selected()`` and ``brushed()`` attach at render, so they don't
need this). If the first reader runs late -- e.g. a chat handler, or an
effect gated on ``input.action_button()`` -- read the accessor once,
unconditionally, at startup to attach it immediately:

```python
@reactive.effect
def _():
plot.clicked() # attach now, so early clicks aren't lost
```

**Updating in place**: re-rendering rebuilds the figure, resetting zoom and
selection. To change a displayed figure instead, read inputs under
`reactive.isolate()` in the render function and modify `.widget` in a
Expand Down
Loading