express.render.DataGrid(self, data, *, width='fit-content', height=None, summary=True, filters=False, editable=False, selection_mode='none', row_selection_mode='deprecated')

Holds the data and options for a data_frame output, for a spreadsheet-like view.


data: pd.DataFrame | PandasCompatible

A pandas DataFrame object, or any object that has a .to_pandas() method (e.g., a Polars data frame or Arrow table).

width: str | float | None = ‘fit-content’

A maximum amount of horizontal space for the data grid to occupy, in CSS units (e.g. "400px") or as a number, which will be interpreted as pixels. The default is fit-content, which sets the grid’s width according to its contents. Set this to 100% to use the maximum available horizontal space.

height: str | float | None = None

A maximum amount of vertical space for the data grid to occupy, in CSS units (e.g. "400px") or as a number, which will be interpreted as pixels. If there are more rows than can fit in this space, the grid will scroll. Set the height to "auto" to allow the grid to grow to fit all of the rows (this is not recommended for large data sets, as it may crash the browser).

summary: bool | str = True

If True (the default), shows a message like “Viewing rows 1 through 10 of 20” below the grid when not all of the rows are being shown. If False, the message is not displayed. You can also specify a string template to customize the message, containing {start}, {end}, and {total} tokens. For example: "Viendo filas {start} a {end} de {total}".

filters: bool = False

If True, shows a row of filter inputs below the headers, one for each column.

editable: bool = False

If True, allows the user to edit the cells in the grid. When a cell is edited, the new value is sent to the server for processing. The server can then return a new value for the cell, which will be displayed in the grid.

selection_mode: SelectionModeInput = ‘none’

Single string or a set/list/tuple of string values to define possible ways to select data within the data frame.

Supported values: * Use "none" to disable any cell selections or editing. * Use "row" to allow a single row to be selected at a time. * Use "rows" to allow multiple rows to be selected by clicking on them individually.

Resolution rules: * If "none" is supplied, all other values will be ignored. * If both "row" and "rows" are supplied, "row" will be dropped (supporting "rows").

row_selection_mode: RowSelectionModeDeprecated = ‘deprecated’

Deprecated. Please use selection_mode= instead.


Type Description
An object suitable for being returned from a @render.data_frame-decorated output function.

See Also


#| standalone: true
#| components: [editor, viewer]
#| layout: vertical
#| viewerHeight: 400

## file:
import pandas  # noqa: F401 (this line needed for Shinylive to load
import as px
from shinywidgets import render_widget

from shiny import reactive, req
from import render, ui

# Load the Gapminder dataset
df =

# Prepare a summary DataFrame
summary_df = (
            "pop": ["min", "max", "mean"],
            "lifeExp": ["min", "max", "mean"],
            "gdpPercap": ["min", "max", "mean"],

summary_df.columns = ["_".join(col).strip() for col in summary_df.columns.values]
summary_df.rename(columns={"country_": "country"}, inplace=True)

# Set up the UI


    "**Instructions**: Select one or more countries in the table below to see more information."

with ui.layout_columns(col_widths=[12, 6, 6]):
    with ui.card(height="400px"):

        def summary_data():
            return render.DataGrid(summary_df.round(2), selection_mode="rows")

    with ui.card(height="400px"):

        def country_detail_pop():
            return px.line(
                title="Population Over Time",

    with ui.card(height="400px"):

        def country_detail_percap():
            return px.line(
                title="GDP per Capita Over Time",

def filtered_df():
    data_selected = summary_data.data_view(selected=True)
    req(not data_selected.empty)
    countries = data_selected["country"]

    # Filter data for selected countries
    return df[df["country"].isin(countries)]