Hi,
I’m currently using dash_ag_grid to construct a dash webapp with features similar to Excel.
I’m dealing with big CSV data, hence I’m using ‘infinite’ rowModel (extually its ‘serverside’).
I’ve activated the EnterpriseModules and using gridOptions like below
dashGridOptions={
"undoRedoCellEditing": True,
"enableRangeSelection": True,
"undoRedoCellEditing": True,
}
I’ve made it editable and when a cell is modified, I’ve synchronized it to modify the corresponding cell in the dataframe through ‘cellValueChanged’ in the callback.
(referenced from Editing and Callbacks | Dash for Python Documentation | Plotly)
The problem arises when I select a range of cells, copy and then paste it elsewhere, as in Excel. Even though multiple cells get modified at once, in the callback, ‘cellValueChanged’ shows information for only one cell (the last one among the modified cells).
Since the rowModel is ‘infinite’, if the modifications are not reflected in the dataframe, the changes will all be lost when the grid is refreshed.
How can I retrieve information for all the modified cells?
I’m sharing the code I’m using for your reference.
import dash_ag_grid as dag
from dash import Dash, Input, Output, html, no_update, callback, State, Patch
import pandas as pd
import dash_bootstrap_components as dbc
app = Dash(__name__)
df = pd.read_csv(
"https://raw.githubusercontent.com/plotly/datasets/master/ag-grid/olympic-winners.csv"
)
columnDefs = [
{
"headerName": "ID",
"maxWidth": 100,
"valueGetter": {"function": "params.node.id"},
},
{"field": "athlete", "minWidth": 150},
{"field": "country", "minWidth": 150},
{"field": "year"},
{"field": "sport", "minWidth": 150},
{"field": "total"},
]
defaultColDef = {
"flex": 1,
"minWidth": 150,
"sortable": False,
"resizable": True,
'editable': True
}
adding_newColumn = dbc.Col(
[
html.Div("New Column:"),
dbc.InputGroup(
[
dbc.Input(
id="new-column-header-input",
placeholder="header",
type="text",
size="sm",
className="smaller-input",
),
dbc.Input(
id="new-column-value-input",
placeholder="value",
type="text",
size="sm",
className="smaller-input",
),
dbc.Button(
"Add",
id='add-new-column-btn',
color="secondary",
size="sm",
className="me-1",
# disabled=True,
),
],
size="sm",
),
],
width=2,
)
app.layout = html.Div(
[
adding_newColumn,
dag.AgGrid(
id="infinite-row-grid",
columnDefs=columnDefs,
defaultColDef=defaultColDef,
rowModelType="infinite",
enableEnterpriseModules=True,
dashGridOptions={
"undoRedoCellEditing": True,
"enableRangeSelection": True,
"undoRedoCellEditing": True,
},
style={"height": "70vh"},
),
html.Div(id="editing-grid-output"),
],
)
@callback(
Output("infinite-row-grid", "getRowsResponse"),
Input("infinite-row-grid", "getRowsRequest"),
Input("infinite-row-grid", "columnDefs"),
)
def infinite_scroll(request, columnDefs):
if request is None:
return no_update
partial = df.iloc[request["startRow"]: request["endRow"]]
return {"rowData": partial.to_dict("records"), "rowCount": len(df.index)}
@callback(
Output("editing-grid-output", "children"), Input("infinite-row-grid", "cellValueChanged")
)
def update(cell_changed):
return f"{cell_changed}"
@callback(
Output("infinite-row-grid", "columnDefs"),
Input("add-new-column-btn", "n_clicks"),
State("new-column-header-input", "value"),
State("new-column-value-input", "value"),
prevent_initial_call=True,
)
def add_column(n, header, value):
global df
df[header] = value
patched_columnDefs = Patch()
patched_columnDefs.append({"field": header, 'editable': True})
print(df.head())
return patched_columnDefs
if __name__ == "__main__":
app.run(debug=True)
Thankyou