serverSide rowModelType in Dash AgGrid

Hello @wowwwn,

Not sure I understand the issue here, here is an updated version that should work:

import dash_ag_grid as dag
from dash import Dash, Input, Output, html, dcc, State
import requests, json
import flask
import pandas as pd

app = Dash(__name__)

server = app.server

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

rowData = df.to_dict('records')

columnDefs = [
    # Row group by country and by year is enabled.
    {"field": "country", "sortable": True, "filter": True, "rowGroup": True, "hide": True},
    {"field": "year", "sortable": True, "filter": True, "rowGroup": True, "hide": True},
    {"field": "athlete", "sortable": True, "filter": True},
    {"field": "age", "sortable": True, "filter": True},
    {"field": "date", "sortable": True, "filter": True},
    {"field": "sport", "sortable": True, "filter": True},
    {"field": "total", "sortable": True, "filter": True, "aggFunc": "sum"},
]

def extractRowsFromData(request, df):
    response = []
    print(request)
    dff = df.copy()
    groupBy = [i['id'] for i in request['rowGroupCols']]
    agg = {i['id']: i['aggFunc'] for i in request['valueCols']}
    if not request['groupKeys']:
        dff = dff.groupby(groupBy[0]).agg(agg).reset_index()
    else:
        for i in range(len(request['groupKeys'])):
            dff = dff[dff[request['rowGroupCols'][i]['id']] == request['groupKeys'][i]]
        if len(request['groupKeys']) != len(groupBy):
            dff = dff.groupby(groupBy[:len(request['groupKeys'])+1]).agg(agg).reset_index()
    dff = dff.sort_values(by=[i['colId'] for i in request['sortModel']], ascending=[i['sort'] == 'asc' for i in request['sortModel']])
    return {'rowData': dff.to_dict('records')[request['startRow']: request['endRow']], 'rowCount': len(dff)}

@server.route('/api/serverData', methods=['POST'])
def serverData():
    response = extractRowsFromData(flask.request.json, df)
    return json.dumps(response)


grid = html.Div(
    [
        dag.AgGrid(
            id="grid",
            columnDefs=columnDefs,
            dashGridOptions={"rowSelection": "multiple", "sideBar": True},
            defaultColDef=dict(
                resizable=True,
            ),
            enableEnterpriseModules=True,
            rowModelType="serverSide",
            style={'overflow': 'auto', 'resize': 'both'}
        ),
    ]
)

app.layout = html.Div(
    [
        dcc.Markdown("Example: Organisational Hierarchy using Tree Data "),
        grid,
    ]
)

app.clientside_callback(
    """async function (id) {
        const updateData = (grid) => {
          var datasource = createServerSideDatasource();
          grid.setServerSideDatasource(datasource);
        };
        var grid;
        grid = await window.dash_ag_grid.getApiAsync(id)
        if (grid) {
            updateData(grid)
        }
        return window.dash_clientside.no_update
    }""",
    Output('grid', 'id'), Input('grid', 'id')
)


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

Take a look at this version and see if it works for you:

import dash_ag_grid as dag
from dash import Dash, Input, Output, html, dcc, State
import requests, json
import flask
import pandas as pd

app = Dash(__name__)

server = app.server

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

rowData = df.to_dict('records')

columnDefs = [
    # Row group by country and by year is enabled.
    {"field": "country", "sortable": True, "filter": True, "rowGroup": True, "hide": True},
    {"field": "year", "sortable": True, "filter": True, "rowGroup": True, "hide": True},
    {"field": "athlete", "sortable": True, "filter": True},
    {"field": "age", "sortable": True, "filter": True},
    {"field": "date", "sortable": True, "filter": True},
    {"field": "sport", "sortable": True, "filter": True},
    {"field": "total", "sortable": True, "filter": True, "aggFunc": "sum"},
]

def extractRowsFromData(request, df):
    response = []
    print(request)
    dff = df.copy()
    groupBy = []
    if request['rowGroupCols']:
        groupBy = [i['id'] for i in request['rowGroupCols']]
    agg = {}
    if request['valueCols']:
        agg = {i['id']: i['aggFunc'] for i in request['valueCols']}
    if not request['groupKeys']:
        if groupBy:
            if agg:
                dff = dff.groupby(groupBy[0]).agg(agg).reset_index()
            else:
                dff = dff.groupby(groupBy[0]).agg('count').reset_index()
    else:
        for i in range(len(request['groupKeys'])):
            dff = dff[dff[request['rowGroupCols'][i]['id']] == request['groupKeys'][i]]
        if len(request['groupKeys']) != len(groupBy):
            if agg:
                dff = dff.groupby(groupBy[:len(request['groupKeys'])+1]).agg(agg).reset_index()
            else:
                dff = dff.groupby(groupBy[:len(request['groupKeys']) + 1]).agg('count').reset_index()
    dff = dff.sort_values(by=[i['colId'] for i in request['sortModel']], ascending=[i['sort'] == 'asc' for i in request['sortModel']])
    return {'rowData': dff.to_dict('records')[request['startRow']: request['endRow']], 'rowCount': len(dff)}

@server.route('/api/serverData', methods=['POST'])
def serverData():
    response = extractRowsFromData(flask.request.json, df)
    return json.dumps(response)


grid = html.Div(
    [
        dag.AgGrid(
            id="grid",
            columnDefs=columnDefs,
            dashGridOptions={"rowSelection": "multiple", "sideBar": True},
            defaultColDef=dict(
                resizable=True,
                enableRowGroup=True,
                enableValue=True,
                enablePivot=True
            ),
            enableEnterpriseModules=True,
            rowModelType="serverSide",
            style={'overflow': 'auto', 'resize': 'both'}
        ),
    ]
)

app.layout = html.Div(
    [
        dcc.Markdown("Example: Organisational Hierarchy using Tree Data "),
        grid,
    ]
)

app.clientside_callback(
    """async function (id) {
        const updateData = (grid) => {
          var datasource = createServerSideDatasource();
          grid.setServerSideDatasource(datasource);
        };
        var grid;
        grid = await window.dash_ag_grid.getApiAsync(id)
        if (grid) {
            updateData(grid)
        }
        return window.dash_clientside.no_update
    }""",
    Output('grid', 'id'), Input('grid', 'id')
)


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

You might need to work with your data some, but this will let you change things about the sidebar. For more info, check here:

3 Likes