Hi all,
I made a table which updates pretty much the entire table when it recon the changes within a cell.
Using Patch(), it can read and write data just fine, but it was too slow and decided to implement clientside_callback.
And I noticed that it doesn’t really work as expected,
the changes are noticeably faster but they are just one execution behind.
I’ve added an example incase my words weren’t clear enough.
It was tested on py3.9.13, dash==2.11.1, dash-ag-grid==2.3.0
from copy import deepcopy
import dash_ag_grid as dag
import numpy as np
import pandas as pd
from dash import Dash, Input, Output, State, clientside_callback, html
app = Dash(__name__)
# df init
df = pd.DataFrame(np.random.randint(0, 10, size=(15, 2)), columns=list("ab"))
df['c'] = df.a + df.b
df.reset_index(inplace=True)
columnDefs = [
{
"headerName": "Editable A",
"field": "a",
"editable": True,
"resizable": True,
},
{
"headerName": "Editable B",
"field": "b",
"editable": True,
},
{
"headerName": "A + B",
"field": "c",
}
]
columnDefsAnimation = deepcopy(columnDefs)
columnDefsAnimation[2]["cellRenderer"] = "agAnimateShowChangeCellRenderer"
defaultColDef = {
"filter": "agNumberColumnFilter",
"resizable": True,
"sortable": True,
}
app.layout = html.Div(
[
# w/ renderer
html.H3("With animation renderer"),
html.Div(
dag.AgGrid(
id="animation-grid",
columnDefs=columnDefsAnimation,
rowData=df.to_dict("records"),
columnSize="sizeToFit",
defaultColDef=defaultColDef,
# setting a row ID is required when updating data in a callback
getRowId="params.data.index",
),
),
# w/o renderer
html.H3("Without animation renderer"),
html.Div(
dag.AgGrid(
id="no-animation-grid",
columnDefs=columnDefs,
rowData=df.to_dict("records"),
columnSize="sizeToFit",
defaultColDef=defaultColDef,
# setting a row ID is required when updating data in a callback
getRowId="params.data.index",
),
),
],
style={"margin": 20},
)
clientside_callback(
"""
function(cellValueChanged, rowData) {
let newRowData = rowData
if (cellValueChanged, rowData) {
newRowData[cellValueChanged.rowIndex]['c'] =
parseFloat(newRowData[cellValueChanged.rowIndex]['a']) +
parseFloat(newRowData[cellValueChanged.rowIndex]['b']);
return [newRowData]
}
return window.dash_clientside.no_update;
}
""",
[Output("no-animation-grid", "rowData")],
[Input("no-animation-grid", "cellValueChanged")],
[State("no-animation-grid", "rowData")],
prevent_initial_call=True
)
clientside_callback(
"""
function(cellValueChanged, rowData) {
let newRowData = rowData
if (cellValueChanged, rowData) {
newRowData[cellValueChanged.rowIndex]['c'] =
parseFloat(newRowData[cellValueChanged.rowIndex]['a']) +
parseFloat(newRowData[cellValueChanged.rowIndex]['b']);
return [newRowData]
}
return window.dash_clientside.no_update;
}
""",
[Output("animation-grid", "rowData")],
[Input("animation-grid", "cellValueChanged")],
[State("animation-grid", "rowData")],
prevent_initial_call=True
)
if __name__ == "__main__":
app.run(debug=True)
There is high chance that I might be missing something
Thanks.