Master Detail

Master detail is an AG Grid Enterprise feature, so you’ll need a license key to use it. See Using AG Grid Enterprise for an example of how to use your license key with Dash AG Grid components.

To add expandable rows within a grid, you can use master detail.

To use the master detail feature to display nested grids within each row of a top-level master grid, your rowData object must have a nested structure like the data in this example.
To use master/detail view:
- Enable enterprise mode by setting enableEnterpriseModules=True.
- Set masterDetail=True.
- Pass detailCellRendererParams to set the display options for the detail grid. It must include at least the following keys:
- detailGridOptions containing columnDefs for the detail grid
- detailColName containing the column name in the data where the detail grid data is stored
- Optional: Set height of detail grid
- For fixed height, set detailRowHeight on dashGridOptions to a number of pixels
- For auto height to fit all data, set detailRowAutoHeight=True on dashGridOptions

from dash import Dash, html
import dash_ag_grid as dag
import os

app = Dash(__name__)

masterColumnDefs = [
    {
        "headerName": "Country",
        "field": "country",
        "cellRenderer": "agGroupCellRenderer",
    },
    {"headerName": "Region", "field": "region"},
    {"headerName": "Population", "field": "population"},
]
detailColumnDefs = [
    {"headerName": "City", "field": "city"},
    {"headerName": "Pop. (City proper)", "field": "population_city"},
    {"headerName": "Pop. (Metro area)", "field": "population_metro"},
]
rowData = [
    {
        "country": "China",
        "region": "Asia",
        "population": 1411778724,
        "cities": [
            {"city": "Shanghai", "population_city": 24870895, "population_metro": "NA"},
            {"city": "Beijing", "population_city": 21893095, "population_metro": "NA"},
            {
                "city": "Chongqing",
                "population_city": 32054159,
                "population_metro": "NA",
            },
        ],
    },
    {
        "country": "India",
        "region": "Asia",
        "population": 1383524897,
        "cities": [
            {
                "city": "Delhi",
                "population_city": 16753235,
                "population_metro": 29000000,
            },
            {
                "city": "Mumbai",
                "population_city": 12478447,
                "population_metro": 24400000,
            },
            {
                "city": "Kolkata",
                "population_city": 4496694,
                "population_metro": 14035959,
            },
        ],
    },
    {
        "country": "United States",
        "region": "Americas",
        "population": 332593407,
        "cities": [
            {
                "city": "New York",
                "population_city": 8398748,
                "population_metro": 19303808,
            },
            {
                "city": "Los Angeles",
                "population_city": 3990456,
                "population_metro": 13291486,
            },
            {
                "city": "Chicago",
                "population_city": 2746388,
                "population_metro": 9618502,
            },
        ],
    },
    {
        "country": "Indonesia",
        "region": "Asia",
        "population": 271350000,
        "cities": [
            {
                "city": "Jakarta",
                "population_city": 10154134,
                "population_metro": 33430285,
            },
        ],
    },
]


app.layout = html.Div(
    [
        dag.AgGrid(
            id="simplified-master-detail-example",
            enableEnterpriseModules=True,
            licenseKey=os.environ["AGGRID_ENTERPRISE"],
            columnDefs=masterColumnDefs,
            rowData=rowData,
            columnSize="sizeToFit",
            masterDetail=True,
            detailCellRendererParams={
                "detailGridOptions": {
                    "columnDefs": detailColumnDefs,
                },
                "detailColName": "cities",
                "suppressCallback": True,
            },
            dashGridOptions={"detailRowAutoHeight": True, "animateRows": False},
        ),
    ]
)


if __name__ == "__main__":
    app.run(debug=True)

Aggregate Row Groups with Nested Grids

Aggregate functions can be applied to any column to populate the row group with values. The simplest way to enable aggregations is with the built-in aggregation functions; sum, min, max, count, avg, first, last. The following snippet shows how these aggregate functions can be applied to columns using aggFunc:

from dash import Dash, html
import dash_ag_grid as dag
import os
import pandas as pd

app = Dash(__name__)


df = pd.read_csv(
    "https://raw.githubusercontent.com/plotly/datasets/master/ag-grid/olympic-winners.csv"
)

app.layout = html.Div(
    [
        dag.AgGrid(
            id="master-detail-aggregate-example",
            enableEnterpriseModules=True,
            licenseKey=os.environ['AGGRID_ENTERPRISE'],
            columnDefs=[
                    {'field': 'country', 'rowGroup': True, 'hide': True},
                    {'field': 'year', 'rowGroup': True, 'hide': True},
                    {'field': 'gold', 'aggFunc': 'sum'},
                    {'field': 'silver', 'aggFunc': 'max'},
                    {'field': 'bronze', 'aggFunc': 'avg'}],
            rowData=df.to_dict("records"),
            columnSize="sizeToFit",
            dashGridOptions={"animateRows": False}
        ),
    ]
)


if __name__ == "__main__":
    app.run(debug=True)

Callback with Nested Grids

In this example, new row data is served using a request/response model, similar to infinite scroll.

from dash import Dash, html, Input, Output, callback
import dash_ag_grid as dag

import os

import time

app = Dash(__name__)
masterColumnDefs = [
    {
        "headerName": "Country",
        "field": "country",
        "cellRenderer": "agGroupCellRenderer",
    },
    {"headerName": "Region", "field": "region"},
    {"headerName": "Population", "field": "population"},
]

detailColumnDefs = [
    {"headerName": "City", "field": "city"},
    {"headerName": "Pop. (City proper)", "field": "population_city"},
    {"headerName": "Pop. (Metro area)", "field": "population_metro"},
]

rowData = [
    {
        "country": "China",
        "region": "Asia",
        "population": 1411778724,
        "cities": [
            {"city": "Shanghai", "population_city": 24870895, "population_metro": "NA"},
            {"city": "Beijing", "population_city": 21893095, "population_metro": "NA"},
            {
                "city": "Chongqing",
                "population_city": 32054159,
                "population_metro": "NA",
            },
        ],
    },
    {
        "country": "India",
        "region": "Asia",
        "population": 1383524897,
        "cities": [
            {
                "city": "Delhi",
                "population_city": 16753235,
                "population_metro": 29000000,
            },
            {
                "city": "Mumbai",
                "population_city": 12478447,
                "population_metro": 24400000,
            },
            {
                "city": "Kolkata",
                "population_city": 4496694,
                "population_metro": 14035959,
            },
        ],
    },
    {
        "country": "United States",
        "region": "Americas",
        "population": 332593407,
        "cities": [
            {
                "city": "New York",
                "population_city": 8398748,
                "population_metro": 19303808,
            },
            {
                "city": "Los Angeles",
                "population_city": 3990456,
                "population_metro": 13291486,
            },
            {
                "city": "Chicago",
                "population_city": 2746388,
                "population_metro": 9618502,
            },
        ],
    },
    {
        "country": "Indonesia",
        "region": "Asia",
        "population": 271350000,
        "cities": [
            {
                "city": "Jakarta",
                "population_city": 10154134,
                "population_metro": 33430285,
            },
        ],
    },
]


app.layout = html.Div(
    [
        dag.AgGrid(
            enableEnterpriseModules=True,
            licenseKey=os.environ["AGGRID_ENTERPRISE"],
            id="nested-grid-detail-table-request-2",
            columnDefs=masterColumnDefs,
            rowData=rowData,
            columnSize="sizeToFit",
            masterDetail=True,
            detailCellRendererParams={
                "detailGridOptions": {
                    "columnDefs": detailColumnDefs,
                },
                "suppressCallback": False,
            },
            dashGridOptions={"detailRowAutoHeight": True, "animateRows": False},
        ),
    ]
)


@callback(
    Output("nested-grid-detail-table-request-2", "getDetailResponse"),
    Input("nested-grid-detail-table-request-2", "getDetailRequest"),
    prevent_initial_call=True,
)
def handle_request(request):
    time.sleep(1)
    return request["data"]["cities"]


if __name__ == "__main__":
    app.run(debug=True)