serverSide rowModelType in Dash AgGrid

Here is if you have data as a df:

app.py

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 = []
    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()
    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"},
            defaultColDef=dict(
                resizable=True,
            ),
            enableEnterpriseModules=True,
            rowModelType="serverSide",
        ),
    ]
)

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

app.clientside_callback(
    """async function (id) {
        const delay = ms => new Promise(res => setTimeout(res, ms));
        const updateData = (grid) => {
          var datasource = createServerSideDatasource();
          grid.setServerSideDatasource(datasource);
        };
        var grid;
            try {
                grid = dash_ag_grid.getApi(id)
            } catch {}
            count = 0
            while (!grid) {
                await delay(200)
                try {
                    grid = dash_ag_grid.getApi(id)
                } catch {}
                count++
                if (count > 20) {
                    break;
                }
            }
            if (grid) {
                updateData(grid)
            }
        return window.dash_clientside.no_update
    }""",
    Output('grid', 'id'), Input('grid', 'id')
)


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

js.file:

async function getServerData(request) {
    response = await fetch('./api/serverData', {'method': 'POST', 'body': JSON.stringify(request),
      'headers': {'content-type': 'application/json'}})
    return response.json()
}

function createServerSideDatasource() {
  const dataSource = {
    getRows: async (params) => {
      console.log('ServerSideDatasource.getRows: params = ', params);
      var result = await getServerData(params.request)
      console.log('getRows: result = ', result);
      setTimeout(function () {
        params.success(result);
      }, 200);
    },
  };
  return dataSource;
}

with support for sorting the columns:

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"},
            defaultColDef=dict(
                resizable=True,
            ),
            enableEnterpriseModules=True,
            rowModelType="serverSide",
        ),
    ]
)

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

app.clientside_callback(
    """async function (id) {
        const delay = ms => new Promise(res => setTimeout(res, ms));
        const updateData = (grid) => {
          var datasource = createServerSideDatasource();
          grid.setServerSideDatasource(datasource);
        };
        var grid;
            try {
                grid = dash_ag_grid.getApi(id)
            } catch {}
            count = 0
            while (!grid) {
                await delay(200)
                try {
                    grid = dash_ag_grid.getApi(id)
                } catch {}
                count++
                if (count > 20) {
                    break;
                }
            }
            if (grid) {
                updateData(grid)
            }
        return window.dash_clientside.no_update
    }""",
    Output('grid', 'id'), Input('grid', 'id')
)


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