I have tried a few things in the forum with no luck. I can’t register and catch a callback when row/s in the detail/child table are selected. Of course the row selection callback on the Master table is easy peasy. Any pointers out there?
Hello @jazzleblue,
You have to add an event listener to the detail grid when it opens and becomes available.
Yeah this callback fires but I don’t know how to catch it/what to do now.
clientside_callback(
"""(id) => {
dash_ag_grid.getApiAsync(id).then((grid) => {
grid.addEventListener('rowGroupOpened', (em) => {
if (em.node.detailNode && em.expanded) {
console.log('Detail Node:', em.node.detailNode);
// Wait for detail grid to be ready
const checkDetailGrid = () => {
const detailGrid = em.node.detailNode.detailGridInfo;
if (detailGrid && detailGrid.api) {
console.log('Detail Grid Info:', detailGrid);
// Add cell value changed listener
detailGrid.api.addEventListener('cellValueChanged', (ed) => {
const newChange = {
...ed,
node: {
id: `${detailGrid.id} - ${ed.node.id}`
}
};
em.api.getGridOption('onCellValueChanged')(newChange);
});
// Add row selection listener
detailGrid.api.addEventListener('rowSelected', (event) => {
const selectedRows = detailGrid.api.getSelectedRows();
const actionTable = grid;
// actionTable.setDetailCellValue('selectedRows', selectedRows, em.node.id);
});
} else {
// If not ready, try again in a short moment
setTimeout(checkDetailGrid, 50);
}
};
checkDetailGrid();
}
})
})
return window.dash_clientside.no_update
}""",
Output("action-table", "id"),
Input("action-table", "id"),
)
You don’t need to add using clientside callbacks anymore, you can have event listeners directly from the grid props.
They get added once the grid becomes available.
Anyways, you need to figure out where you want to send the data. You could use set_props to send the data to a dcc.store.
Testing this out and I don’t get the callback to fire/console log"
dag.AgGrid(
id="action-table",
masterDetail=True,
columnDefs=action_group_column_defs,
rowData=[],
dashGridOptions={
"rowSelection": False,
"suppressRowClickSelection": True,
"detailRowAutoHeight": True,
},
enableEnterpriseModules=True,
style={"height": "calc(100vh - 450px)", "width": "100%"},
className="ag-theme-alpine-dark",
getRowId="params.data.id",
detailCellRendererParams={
"detailGridOptions": {
"columnDefs": action_group_item_column_defs,
"rowSelection": "multiple",
"suppressRowClickSelection": True,
"checkboxSelection": True,
},
"eventListeners": {
"cellValueChanged": "[actionItemCellValueChanged(params)]"
},
"detailColName": "action_items",
"suppressCallback": True,
},
)
with this js defined
dagfuncs.actionItemCellValueChanged = function (params) {
console.log('Action item cell value changed:', params);
}
any idea where I went sideways. Cheers.
You have to add it to the main grid:
dag.AgGrid(
id="action-table",
masterDetail=True,
columnDefs=action_group_column_defs,
rowData=[],
dashGridOptions={
"rowSelection": False,
"suppressRowClickSelection": True,
"detailRowAutoHeight": True,
},
enableEnterpriseModules=True,
style={"height": "calc(100vh - 450px)", "width": "100%"},
className="ag-theme-alpine-dark",
getRowId="params.data.id",
"eventListeners": {
"rowGroupOpened": ["MasterDetailListeners(params, setGridProps)"]
},
detailCellRendererParams={
"detailGridOptions": {
"columnDefs": action_group_item_column_defs,
"rowSelection": "multiple",
"suppressRowClickSelection": True,
"checkboxSelection": True,
},
"detailColName": "action_items",
"suppressCallback": True,
},
)
dagfuncs.MasterDetailListeners = (em, setGridProps) => {
if (em.expanded) {
gridDetail = em.node.detailNode.detailGridInfo
gridDetail.api.addEventListener('cellValueChanged',
(ed) => {
const newChanges = {...ed, node: {id:`${ed.node.id}|${gridDetail.id}`}}
em.api.getGridOption('onCellValueChanged')(ed)
})
gridDetail.api.addEventListener('cellClicked', (ed) => {
const newChanges = {...ed, node: {id:{'MasterDetail': true, id: `${ed.node.id}`}}}
em.api.getGridOption('onCellClicked')(newChanges)
})
}
}
This is what I do.
Do you have any idea why this
gridDetail.api.addEventListener('selectionChanged', (ed) => {
const selectedRows = gridDetail.api.getSelectedRows();
em.api.getGridOption('onSelectionChanged')(selectedRows)
});
isn’t picked up by
@callback(Output("output", "children"), Input("action-table", "selectedRows"))
def cell_clicked(cell_data):
if cell_data:
print(cell_data)
return f"Cell clicked: {cell_data}"
return "No cell clicked yet."
When a row is selected in the Master grid it works but not in the child/detail grids.
The selectedRows
is set to go back to the parent grid, that is why I dont recommend using it…
Ok - so how do i get the detail/child row selected back on the dash callback side? I just need to get the children selected rows into a Store.
Use a dcc.Store
and use dash_clientside.set_props('storeid', {data: 'selectedrowdata'})
Roger. I didn’t see a way to get_props from the store and add/modify the data. Is there a clever way to get all the selected rows for multiple detail grids to send to the store?
You could have a store that uses a key to dedicate which detail grid selections it is talking about, and then compile them in the backend.
Things to note though, once you collapse and reopen your selections will be destroyed. You could work around this potentially by recalling the selections from that store based upon grid ready for the detail grid.