Dash 3.3.0 added support for patching in clientside callbacks. Plus, Dash Table is being deprecated so I’m migrating to Dash AG Grid. There are several features that worked well in Dash Table that do not (yet) work well in AG Grid. One of which is persisting data in edited tables.
I’m trying to migrate a workaround for persisting data in editable AG Grid tables, from this post, copied below for reference:
@callback(
Output("store", "data"),
Output("table", "rowData"),
Input("table", "cellValueChanged"),
State("store", "data")
# it's important that prevent_initial_call=False (the default)
)
def update(cells, edits):
row_id_var = 'rowId'
if cells :
cells_info = [{k:c[k] for k in [row_id_var, 'colId', 'value']} for c in cells]
# you may want to include some logic to check if previous edits have been made to the same cells and remove those
# keeping old edits won't cause a problem anyway
edits += cells_info
return edits, dash.no_update
else :
saved_rows = Patch()
for e in edits:
index = e[row_id_var]
saved_rows[index][e['colId']] = e['value']
return dash.no_update, saved_rows
I’m trying to use patching in clientside callbacks to speed up the computation.
This is the code I have at the moment, but it’s not working
app.clientside_callback(
"""
function(cells, edits) {
const row_id_var = "rowId";
if (cells && cells.length > 0) {
// Extract only rowIndex, colId, and value from each changed cell
const cells_info = cells.map(c => {
return {
rowId: c[row_id_var],
colId: c.colId,
value: c.value
};
});
// Append new edits to stored edits
const new_edits = (edits || []).concat(cells_info);
// Return: store data updated, table rowData unchanged (no_update)
return [new_edits, dash_clientside.no_update];
} else {
// Patch the saved rows with existing edits
// https://dash.plotly.com/clientside-callbacks#partial-property-updates
const saved_rows = new dash_clientside.Patch;
edits.forEach(e => {
const index = e[row_id_var];
// THIS LINE BELOW FAILS!
saved_rows.assign([index, e.colId], e.value);
});
// Return: store data unchanged (no_update), table patched data. Need to call .build() to finalize patch object
return [dash_clientside.no_update, saved_rows.build()];
}
}
""",
[Output("store", "data"), Output({"table", "rowData")],
[Input({"table", "cellValueChanged"), State("store", "data")],
prevent_initial_call=False,
)
The line saved_rows.assign([index, e.colId], e.value); fails. This is trying to replicate saved_rows[index][e['colId']] = e['value'] from the original Python code in the Github link above. Basically what I’m trying to do is overwrite an array element at a specific index.
I’m very much a novice at JavaScript. I am not sure if indexing an array is the same as traversing a path that you’re supposed to do in assign(). From the docs it says:
.assign(path, value) - Assign a new value to a property
But this is not really array indexing I guess?
Anyway, the error I get is
Uncaught Error: Invalid argument `rowData` passed into AgGrid with ID "table". Expected an array. Was supplied type `object`. Value provided:
{
"0": {
"colidentifier1": "valuetoputhere1",
"colidentifier2": "valuetoputhere2",
"maximum_capacity": "valuetoputhere3"
},
...
}
Any pointers on how I can fix this code?