I am trying to present 10 unique options (chips) for each row using dash-ag-grid and dmc.ChipGroup as a custom cell renderer.
The issue I run into is that for more than a trivial amount of rows, the application first stops registering changes and eventually becomes completely unresponsive. Developer tools hints at a memory leak. I am not familiar with js/react and have put this together from other examples + GPT so hard for me to troubleshoot appropriately. Hoping someone (like the resident forum genius @AnnMarieW) can help
Package Versions
dash==2.17.0
dash-mantine-components==0.12.1
dash-ag-grid==31.2.0
Python MRE
import dash
from dash import html, Input, Output, State
from dash.exceptions import PreventUpdate
import dash_ag_grid as dag
import pandas as pd
import dash_mantine_components as dmc
app = dash.Dash(__name__)
no_of_rows = 2
data = {
"RecommendedMatches": [
[
{
"value": f"Match {i}",
"children": f"This is Match {i}",
"tooltip": f"Custom Tooltip {i}",
}
for i in range(1, 11)
]
]
* no_of_rows,
"SelectedChip": ["X"] * no_of_rows, # meaningless initial value for mre
}
df = pd.DataFrame(data)
df["index"] = df.index
# Define the ag-Grid column definitions
column_defs = [
{
"headerName": "index",
"field": "index",
# "hide": True,
},
{
"headerName": "Recommended Matches",
"field": "RecommendedMatches",
"cellRenderer": "DMC_ChipGroup",
"autoHeight": True,
},
{
"headerName": "Selected Chip",
"field": "SelectedChip",
},
]
# Create the Dash layout
app.layout = html.Div(
[
dmc.LoadingOverlay(
dag.AgGrid(
id="grid",
rowModelType="clientSide",
columnDefs=column_defs,
rowData=df.to_dict("records"),
columnSize="sizeToFit",
getRowId="params.data.index",
style={"height": "600px"},
),
),
]
)
# Callback to capture the selected chip value
@app.callback(
[
Output("grid", "rowTransaction"),
],
[
Input("grid", "cellRendererData"),
],
[
State("grid", "rowData"),
],
prevent_initial_call=True,
)
def display_selected_chip(cell_changed, grid_data_raw):
if cell_changed and "value" in cell_changed:
new_value = cell_changed["value"]
ix_changed = cell_changed["rowId"]
grid_data_raw = pd.DataFrame(grid_data_raw)
grid_data = grid_data_raw.loc[grid_data_raw["index"] == int(ix_changed)].copy(
deep=True
)
grid_data["SelectedChip"] = new_value
print(ix_changed, new_value)
return [
{
"update": grid_data.to_dict(orient="records"),
},
]
raise PreventUpdate
if __name__ == "__main__":
app.run_server(host="0.0.0.0", debug=True, port=8282)
dashAgGridFunctions.js
////////////////////////////////////////
// CHIP GROUP
///////////////////////////////////////
var dagcomponentfuncs = (window.dashAgGridComponentFunctions = window.dashAgGridComponentFunctions || {});
dagcomponentfuncs.DMC_ChipGroup = function (props) {
const { setData, colId, node, rowIndex, value } = props;
const [selectedChip, setSelectedChip] = React.useState(value[0]?.value || null);
function handleChipClick(chipValue) {
console.log("Selected chip value:", chipValue); // Debug statement to print the selected chip value
setSelectedChip(chipValue);
if (setData) {
setData(chipValue);
}
}
return React.createElement(
window.dash_mantine_components.ChipGroup,
{ onChange: handleChipClick, multiple: false, value: selectedChip, style: { display: 'grid', gridTemplateColumns: 'repeat(2, 1fr)', gap: '1px' }, align: 'center', position: 'center' },
value.map(chipData =>
React.createElement(window.dash_mantine_components.Tooltip, {
key: chipData.value, // Ensure each Tooltip has a unique key
label: React.createElement(window.dash_core_components.Markdown, {
children: chipData.tooltip,
dangerously_allow_html: true,
}),
multiline: true,
},
React.createElement(window.dash_mantine_components.Chip, {
key: chipData.value, // Ensure each Chip has a unique key
value: chipData.value,
variant: chipData.variant,
color: chipData.color,
size: 'sm',
}, chipData.children)
)
)
);
};
With the no_of_rows parameter set to 2, everything works as expected without any errors.
When the grid is larger, e.g. no_of_rows = 100, it works for a selection or two but then the applicaiton becomes unresponsive
When no_of_rows is large (e.g. no_of_rows = 100)
Any help at all would be greatly appreciated - my entire application bar this feature is ready and I would hate to have to change things up at this stage.
P.S > For the MRE, to make it easier, I’ve kept the options consistent in all rows. However, in my application each row will have a list of unique 10 options hence the usual RadioGroup example where options are set at the column level does not work for my use case.