AgGrid ignores prevent_initial_call

Is it true that when rowData is inserted on the fly when dash is creating its layout, that it fires a callback, even though prevent_initial_call is set or am I missing something?

from dash import Dash, html, callback, ctx
from dash.dependencies import Input, Output
import dash_ag_grid as dag

app = Dash(__name__)

app.layout = html.Div([
    html.Div(id="dummy-div-1"),
    html.Div(id="dummy-div-2"),
    dag.AgGrid(
        id='grid',
        columnDefs=[
            {'headerName': 'Make', 'field': 'make'},
        ],
        rowData=[
            {'make': 'Toyota', 'model': 'Celica', 'price': 35000},
        ],
    )
])


@callback(
    Output("grid", "virtualRowData"),
    Input("dummy-div-1", "children"),
    prevent_initial_call=True,
)
def _out(_):
    print(f"out: {ctx.triggered}")
    return "?"


@callback(
    Output("dummy-div-2", "children"),
    Input("grid", "virtualRowData"),
    prevent_initial_call=True,
)
def _in(_):
    print(f"in: {ctx.triggered}")
    return "!"


if __name__ == '__main__':
    app.run_server(debug=True, port=7000)

output:

in: [{'prop_id': 'grid.virtualRowData', 'value': [{'make': 'Toyota', 'model': 'Celica', 'price': 35000}]}]

If you want virtualRowData, then you should pass the rowData as the virtualRowData. When the grid loads, it converts the virtualRowData from none to populated.

1 Like

@jinnyzor
Sorry, I don’t understand what you mean.
What I want to get is that the ag grid does not fire a callback when initially loaded and filled with data when the app loads

I mean, this even happens when no data is loaded initially:

from dash import Dash, html, callback, ctx
from dash.dependencies import Input, Output
import dash_ag_grid as dag

app = Dash(__name__)

app.layout = html.Div([
    html.Div(id="dummy-div-1"),
    html.Div(id="dummy-div-2"),
    dag.AgGrid(
        id='grid',
    )
])


@callback(
    Output("grid", "virtualRowData"),
    Input("dummy-div-1", "children"),
    prevent_initial_call=True,
)
def _out(_):
    print(f"out: {ctx.triggered}")
    return "?"


@callback(
    Output("dummy-div-2", "children"),
    Input("grid", "virtualRowData"),
    prevent_initial_call=True,
)
def _in(_):
    print(f"in: {ctx.triggered}")
    return "!"


if __name__ == '__main__':
    app.run_server(debug=True, port=7500)

Output:
in: [{'prop_id': 'grid.virtualRowData', 'value': []}]

This cannot be intended, feels more like a bug to me

The grid has virtualRowData as None.

Once the grid is loaded, if the grid is clientside this will update to what ever rowData is there, so for this, it’s just .

To run a callback from the virtualRowData, I recommend checking to make sure it has data first.

if virtualRowData:
    # rest of code

Yeah, well ok I’ll do that.
It’s just that I assumed that’s what prevent_initial_callback=True is for.
I see the point but I still don’t understand why the callback fires in my second example.
The grid is loaded and there is no (not even [], just none at all) rowData, hence no virtualRowData and still the callback with prevent_initial_call=True fires with virtualRowData=[] as trigger. I know, you said that on load its None and then “filled” with [] but I just don’t think that quite consistent or logical in a way. With the same logic applied on a silly example, a dcc.Dropdown with someoptions={...} would should also fire when loading its option properties, shouldn’t it, even if none are set?

prevent_initial_call is to prevent the initial loading of values from triggering a callback, these will have no trigger in the ctx.

virtualRowData is not passed in the initial state, therefore updating it will cause a callback, because this is how dash is designed. This will have the virtualRowData trigger in the ctx.

virtualRowData will not exist inside of non-clientside models. So, not infinite or serverSide models will give you back the virtualRowData


Mess around with these examples, see how the virtualRowData doesnt populate when in infinite, and the callback is not triggered if you send a [] to it.

from dash import Dash, html, callback, ctx
from dash.dependencies import Input, Output
import dash_ag_grid as dag

app = Dash(__name__)

app.layout = html.Div([
    html.Div(id="dummy-div-1"),
    html.Div(id="dummy-div-2"),
    dag.AgGrid(
        id='grid',
        # virtualRowData=[]
        rowModelType='infinite'
    )
])


@callback(
    Output("grid", "virtualRowData"),
    Input("dummy-div-1", "children"),
    prevent_initial_call=True,
)
def _out(_):
    print(f"out: {ctx.triggered}")
    return "?"


@callback(
    Output("dummy-div-2", "children"),
    Input("grid", "virtualRowData"),
    prevent_initial_call=True,
)
def _in(_):
    print(f"in: {ctx.triggered}")
    return "!"


if __name__ == '__main__':
    app.run_server(debug=True, port=7500)
1 Like

thanks for the input and insight