2025, Dec 31 19:00
How to Programmatically Select Rows in a Shiny for Python DataGrid using update_cell_selection()
Learn to programmatically control row selection in a Shiny for Python DataGrid with update_cell_selection(). Keep the UI in sync with server-side state.
Programmatically controlling row selection in a Shiny for Python DataGrid is a common need when the UI should reflect server-side state or user inputs from other widgets. If you built a DataGrid and want to switch the selected row via code rather than manual clicks, there is a straightforward way to do it.
Baseline setup that only supports manual selection
Consider a simple DataGrid with row selection enabled. It renders correctly and supports manual selection, but there’s no server-side hook to change the selection once rendered.
from shiny import ui, render
ui.output_data_frame("view")
@render.data_frame
def view():
some_df = ...
return render.DataGrid(some_df, selection_mode="row")
What’s actually missing
The grid above defines the table and enables row selection, but it doesn’t expose any server-side mechanism to update the current selection after render. To change the selection from Python, you need to explicitly send a selection instruction to the DataGrid. Shiny for Python provides a method that does exactly that.
Solution: update selection via update_cell_selection()
The DataGrid returned by a data frame renderer exposes the method update_cell_selection(). It accepts a configuration describing what to select. For row selection, it takes a mapping with type set to "row" and rows set to the target row index. This call must be made from an async reactive context and awaited. Below is a complete example wiring a select input to the DataGrid’s selection.
from shiny import ui, render, App, reactive
import pandas as pd
src = pd.DataFrame({"Row": ["Row Number 0", "Row Number 1", "Row Number 2"]})
page = ui.page_fluid(
ui.input_select(
"pick_row",
"Which row shall be selected?",
choices=["Choose", 0, 1, 2]
),
ui.output_data_frame("tbl")
)
def srv(inpt, out, sess):
@render.data_frame
def tbl():
return render.DataGrid(src, selection_mode="row")
@reactive.Effect
@reactive.event(inpt.pick_row)
async def apply_selection():
if inpt.pick_row() == "Choose":
return
cfg = {"type": "row", "rows": int(inpt.pick_row())}
await tbl.update_cell_selection(cfg)
app = App(page, srv)
Why this matters
Server-driven selection unlocks a better UX for data exploration and app logic. You can synchronize the grid with external inputs, restore state after navigation, or programmatically highlight a row based on previous computations. Without update_cell_selection(), the grid remains passive and reacts only to direct user clicks.
Takeaways
If you need to alter DataGrid selection from Python, call update_cell_selection() on the rendered DataGrid object from an async reactive context, passing a mapping like {"type": "row", "rows": index}. This gives you precise control over row selection and keeps your app’s UI in sync with server-side state.