render_ipydatagrid
render_ipydatagrid class
Reactively render a pandas DataFrame as an interactive ipydatagrid data grid.
Usage Source
render_ipydatagrid(
_fn: Optional[ValueFn[ValueT]] = None,
*,
width: Optional[str] = None,
height: Optional[str] = None,
fill: Optional[bool] = None,
fillable: Optional[bool] = None,
rate_policy: Optional[RatePolicy] = None,
rate_delay: Optional[float] = None,
)@render_ipydatagrid is a decorator that creates a render function – a function that returns the grid to display and re-runs when the reactive values it reads change:
import pandas as pd
from ipydatagrid import DataGrid
from shinywidgets import render_ipydatagrid
df = pd.DataFrame({"a": [1, 2, 3], "b": ["x", "y", "z"]})
@render_ipydatagrid
def grid():
return DataGrid(df, selection_mode="row")The render function may return either a pandas.DataFrame (which is coerced to an ipydatagrid.DataGrid; requires pip install 'shinywidgets[ipydatagrid]') or an ipydatagrid.DataGrid widget. Pass a DataGrid to customize the grid (e.g., selection_mode, editable, or cell renderers).
Note
Accessing the rendered widget: the render function gains two read-only attributes: .value, the value it most recently returned, and .widget, the rendered DataGrid instance. Widget state (e.g., selections) can also be read reactively with .read("some_trait") (a shortcut for reactive_read() on .widget).
Responding to user interaction: read what the user does in the grid with .selected(), .clicked_cell(), and .edited_cell().
Mutating the widget: use .widget to update the rendered grid in place; trait changes on the widget are synced to the browser.
Some ipydatagrid behaviors worth knowing about:
- A returned DataFrame uses ipydatagrid’s default
selection_mode="none", soselectionsstays empty; returnDataGrid(df, selection_mode="row")(or"cell"/"column") to let users select. selectionsindex the grid as displayed (after any sort or filter), so map them through.widget.get_visible_data();.visible_data()returns those displayed rows as a data frame, reactively.- The grid’s light/dark palette follows the app’s bslib color mode (e.g.,
ui.input_dark_mode). ipydatagrid freezes the palette when a grid view is created, so toggling dark mode re-themes only grids rendered after the toggle (re-render the output to re-theme an existing grid). DataGrid.select(),DataGrid.clear_selection()and cell edits modify the widget’s state in place, which doesn’t triggerreactive_read(). Assign a new list to.widget.selectionsinstead, and use.widget.on_cell_change()to react to edits.- Cell renderers and scales are widgets too, so create them inside the render function rather than at import time.
Parameters
width : Optional[str] = None-
A CSS length unit (e.g.,
"400px"or"100%") for the output’s width. height : Optional[str] = None-
A CSS length unit for the output’s height. When
None(the default), the output is designed to fill the height of its parent container (seefillandfillable). fill : Optional[bool] = None-
Whether the output should grow or shrink to fit its parent container. When
None(the default), this isTrueifheightis not specified. fillable : Optional[bool] = None-
Whether the output container should fill available space (scrolling its contents on overflow). When
None(the default), this isTrueifheightis not specified. rate_policy : Optional[RatePolicy] = None-
How to rate-limit
selected()(debounced by default) andreactive_read()on the widget:"debounce"or"throttle".None(the default) keeps the debounce, and debouncesreactive_read()only ifrate_delayis given. rate_delay : Optional[float] = None-
The rate-limit window in seconds (default 0.25).
0disables rate limiting. Each :which :
See also
output_widget(): in Shiny Core, the UI needs this to hold the output (Shiny Express displays it where the render function is defined).
Methods
clicked_cell() |
The most recently clicked cell, or None until the first click: {"region", "column", "column_index", "row", "primary_key_row", "cell_value"}, where row is the visible row and primary_key_row the data row (they differ after a sort). Kept across re-renders until the user clicks the new grid. |
edited_cell() |
The most recent cell edit, or None until the first edit: {"row", "column", "column_index", "value"}, where row is the data row. The widget’s data is already updated when this fires. Kept across re-renders until the next edit – after a re-render or data replacement with new rows, a retained row position can point at a different record, so key follow-up lookups off .widget.data’s index at read time rather than the position. |
selected() |
The grid’s current selection rectangles, as [{"r1", "r2", "c1", "c2"}, ...] (inclusive), in visible row/column coordinates — i.e., after any sort or filter. Map them to data rows with .widget.get_visible_data() (or use visible_data()). |
visible_data() |
The grid’s rows as currently displayed (after its sort and filter), as a pandas data frame — the selected() rectangles’ coordinate space, so visible_data().iloc[r1:r2 + 1] maps a selection to rows. |
clicked_cell()
render_ipydatagrid.clicked_cell()The most recently clicked cell, or None until the first click: {"region", "column", "column_index", "row", "primary_key_row", "cell_value"}, where row is the visible row and primary_key_row the data row (they differ after a sort). Kept across re-renders until the user clicks the new grid.
Fires in any selection_mode, including "none", and for column-header clicks (region="column-header"). Not rate-limited.
edited_cell()
render_ipydatagrid.edited_cell()The most recent cell edit, or None until the first edit: {"row", "column", "column_index", "value"}, where row is the data row. The widget’s data is already updated when this fires. Kept across re-renders until the next edit – after a re-render or data replacement with new rows, a retained row position can point at a different record, so key follow-up lookups off .widget.data’s index at read time rather than the position.
Requires editable=True. Also fires for Python-side set_cell_value*() calls. Not rate-limited.
selected()
render_ipydatagrid.selected()The grid’s current selection rectangles, as [{"r1", "r2", "c1", "c2"}, ...] (inclusive), in visible row/column coordinates — i.e., after any sort or filter. Map them to data rows with .widget.get_visible_data() (or use visible_data()).
[] while nothing is selected, and after a sort (sorting clears the selection). Requires selection_mode other than "none"; a plain data frame return uses "none", so return DataGrid(df, selection_mode="row") to let users select.
Dragging a selection rectangle reports continuously (on every pointer move), so this accessor is debounced by default (0.25 s; see the renderer’s rate_policy/rate_delay).
On re-render, the new grid re-seeds this from its own selections trait ([] unless the render function pre-selects). But replacing the data in place (grid.data = df) does not clear the selection – ipydatagrid keeps it, so the rectangles then refer to positions in the old frame. Clear it yourself when replacing data (grid.selections = []), and prefer keying selected rows by the frame’s index (via visible_data()) over positions, so lookups survive data changes.
visible_data()
render_ipydatagrid.visible_data()The grid’s rows as currently displayed (after its sort and filter), as a pandas data frame — the selected() rectangles’ coordinate space, so visible_data().iloc[r1:r2 + 1] maps a selection to rows.
The whole frame until the user sorts, filters, or edits, and an empty frame when the filter matches nothing. May be briefly stale after a Python-side data replacement (grid.data = df) while a filter/sort is active, until the browser re-syncs the row map. Not rate-limited.