Here is a starting point with working with their example:
import dash_ag_grid as dag
from dash import Dash, Input, Output, html, dcc, State
import requests, json
app = Dash(__name__)
rowData = requests.get('https://www.ag-grid.com/example-assets/small-tree-data.json').json()
grid = html.Div(
[
dcc.Store(id='gridData', data=rowData),
dag.AgGrid(
id="grid",
columnDefs= [
{"field": 'employeeId', "hide": True},
{"field": 'employeeName', "hide": True},
{"field": 'jobTitle'},
{"field": 'employmentType'},
],
defaultColDef={
"flex": 1,
},
dashGridOptions={
"autoGroupColumnDef": {
"field": "employeeName",
"cellRendererParams": {
"function": "groupRenderer"
},
},
"treeData": True,
"isServerSideGroupOpenByDefault": {'function': 'params ? params.rowNode.level < 2 : null'},
"isServerSideGroup": {'function': 'params ? params.group : null'},
"getServerSideGroupKey": {"function": 'params ? params.employeeId : null'}
},
enableEnterpriseModules=True,
rowModelType="serverSide",
),
]
)
app.layout = html.Div(
[
dcc.Markdown("Example: Organisational Hierarchy using Tree Data "),
grid,
]
)
app.clientside_callback(
"""async function (id, data) {
const delay = ms => new Promise(res => setTimeout(res, ms));
const updateData = (data, grid) => {
var fakeServer = createFakeServer(data);
var datasource = createServerSideDatasource(fakeServer);
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(data, grid)
}
return window.dash_clientside.no_update
}""",
Output('grid', 'id'), Input('grid', 'id'), State('gridData', 'data')
)
if __name__ == "__main__":
app.run(debug=True)
And then the functions that drive it:
function createFakeServer (fakeServerData) {
const fakeServer = {
data: fakeServerData,
getData: function (request) {
function extractRowsFromData(groupKeys, data) {
if (groupKeys.length === 0) {
return data.map(function (d) {
return {
group: !!d.children,
employeeId: d.employeeId,
employeeName: d.employeeName,
employmentType: d.employmentType,
jobTitle: d.jobTitle,
};
});
}
var key = groupKeys[0];
for (var i = 0; i < data.length; i++) {
if (data[i].employeeId === key) {
return extractRowsFromData(
groupKeys.slice(1),
data[i].children.slice()
);
}
}
}
return extractRowsFromData(request.groupKeys, this.data);
},
};
return fakeServer;
}
function createServerSideDatasource(fakeServer) {
const dataSource = {
getRows: (params) => {
console.log('ServerSideDatasource.getRows: params = ', params);
var allRows = fakeServer.getData(params.request);
var request = params.request;
var doingInfinite = request.startRow != null && request.endRow != null;
var result = doingInfinite
? {
rowData: allRows.slice(request.startRow, request.endRow),
rowCount: allRows.length,
}
: { rowData: allRows };
console.log('getRows: result = ', result);
setTimeout(function () {
params.success(result);
}, 200);
},
};
return dataSource;
}
dagfuncs.groupRenderer = function (){
return {
innerRenderer: (params) => {
console.log(params)
// display employeeName rather than group key (employeeId)
return params.data.employeeName;
}
}
}
The easiest way would probably be some way to update the getData
of the createFakeServer
to be responsive from a backend process like an api call to your server.