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},
),
]
)
if __name__ == "__main__":
app.run(debug=True)
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 json
import os
app = Dash(__name__)
with open("dash_docs/assets/example-data/olympic-winners.json", encoding="utf-8") as json_file:
data = json.load(json_file)
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=data,
columnSize="sizeToFit",
defaultColDef=dict(
resizable=True,
),
),
]
)
if __name__ == "__main__":
app.run(debug=True)
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},
),
]
)
@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)