How to prevent triggering of Ag-grid cellValueChanged event caused by setValueData() during periodic update?

I have few columns within AG-Grid are being updated every second using setValueData() within a client-side callback. I also have another server-side callback for the cellValueChanged event to handle cell edits made by users on the rest of the columns in the grid. Everything is working well except that cellValueChanged is being unnecessarily triggered every second due to setValueData() , in addition to being triggered by user-edited cells. I am looking for a solution to prevent the cellValueChanged event from being triggered by setValueData() .

import dash
import dash_ag_grid as dag
from dash import html, dcc, Output, Input, State, no_update
import time
import json

app = dash.Dash(__name__)

columnDefs = [{"field": "Update1", "editable": False}, {"field": "Update2", "editable": False}, {"field": "Edit1", "editable": True}, {"field": "Edit2", "editable": True}]
rowData = [{"Update1": 1, "Update2": 2, "Edit1": 3, "Edit2": 4} for i in range(10)]

grid = dag.AgGrid(
    id="grid",
    columnDefs=columnDefs,
    rowData=rowData,
    #enableCellChangeFlash=True,
    getRowId="params.data.Update1",
)

app.layout = html.Div([
    grid,
    dcc.Interval(id="interval", interval=2000, n_intervals=0)
])

@app.callback(
    Output("grid", 'rowData',allow_duplicate=True),
    Input("grid", 'cellValueChanged'),
    State("grid","rowData"),
     prevent_initial_call = True,
)
def udpdate_grid(cell_value_changed, row_data):
    if ((cell_value_changed[0]['colId'] == 'Edit1') or (cell_value_changed[0]['colId'] == 'Edit2')):
        print("Desirable Trigger")
        return row_data
    else:
        print("Undesirable Trigger")
        no_update

app.clientside_callback(
    """
    async function(n_intervals) {
        const gridApi = dash_ag_grid.getApi('grid');
        if (gridApi) {
            const rowIndex = Math.floor(Math.random() * 8);
            const colIndex = Math.floor(Math.random() * 2);
            const colId = ['Update1', 'Update2'][colIndex];
            const rowNode = gridApi.getDisplayedRowAtIndex(rowIndex + 1);
            if (rowNode) {
                rowNode.setDataValue(colId, Math.random());
            }
        }
        return window.dash_clientside.no_update;
    }
    """,
    dash.dependencies.Output("grid", "rowData"),
    dash.dependencies.Input("interval", "n_intervals"),
    prevent_initial_call=True,
)

if __name__ == "__main__":
    app.run_server(debug=True)

Hello @Jvadalia,

There isn’t really a way to keep that from happening, as the data is changing in the cell. I get around this by grouping the callbacks, but I don’t think that would work for you.

I need to process user edited data using cellChangedValue while other columns are being updated periodically which are read from sensors. Undesired triggering of cellChangedValue every second causes unnecessary network traffic even it returns no-update. Not sure about grouping the callbacks.

What are you using the data from the backend for?
For me, I have a changelog that captures all edits clientside, then upon button push it sends the updates to the server.

Could you use the valueGetter instead of setting the data value for the functions?

The backend is configuring hardware based on user edited values in the grid. As well every second server-side callback collects stats from hardware and passes it to clientside callback to update grid and chart. I don’t see how valueGetter can be used instead of cellValueChanged in this design!

What are you using setDataValue for? This is what is altering the clientside data. If this doesnt need to be used, then you can just use valueGetter to have the data display on the clientside without altering the data.

setDataValue is used in the clientside callback to update statistics every second in the grid. The stats are collected from hardware in the server-side callback. The stats data are passed to clientside using dcc.store. My example mimics my simplified implementation. In the example I am generating random data. I am not sure how to use valueGetter to update grids with stats which are collected serverside and stored in dcc.store.

You should be able to use rowTransaction to update data directly in this instance. Just be sure to use getRowId to target, you also need all the data to pass back.

In this instance, you can use rowTransaction and cellValueChanged at the same time to keep from callback being triggered at the same time.


Other than that, you can remove the event listener from the grid using the api and implement your own…