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.