Few questions regarding AG-Grid

thanks,
I must process deeper your suggestion…will talk to 'chat" to get more help ;-)…

will rowTransaction let me avoid rerender whole grid, and allow for normal usage of grid as it’d be excel?
thanks again
btw
whenever I change code in callback, the app keeps seeing old code, please check printscreens, I change your suggestioin from "! "to “not” but Python still shows an error, restarting pycharm makes not difference.
1
Untitled

Yes, this should allow for it.

’ Hi jinnyzor,
your solution works!!! many thanks.
so my grid is refreshing transactions every 10secs. but …now I’d like grid to refresh every 10secs but only when user is not editing cell… so I took 2 veriables : intervals and cellClicked to my callback
but “cellClicked” it’s not the solution… any idea what other method would help me with refreshing grid every 10sec. but only if user is not editing?

@callback ( Output(‘grid-invoicing’,‘rowTransaction’),
[
Input(‘interval-refresh-invoicing’,‘n_intervals’),
State(‘grid-invoicing’, ‘cellClicked’)
]
)
)

def update_grid(intervals,cellclicked):

    while cellclicked != True:
        if intervals:
            print(intervals)
            conn = engine.connect()
            df_invoicing_update = pd.read_sql_query(con=conn, sql=sql_query(query))
            conn.close()
            return( {'update': df_invoicing_update.to_dict('records'),'remove': df_invoicing_update.to_dict('records'),'add': df_invoicing_update.to_dict('records')})
        else:
            return

Hello @acidkans,

You’ll need to do something like this:

Add to layout

dcc.Input(id=“cell_editing”, style={“display”: “none”})

For the grid, you need to use the api in a clientside callback to add listeners to cellEditingStarted and cellEditingStopped:

app.clientside_callback(
   “”” function (id) {
   dash_ag_grid.getApiAsync(id).then((grid) => {
      grid.addEventListener(“cellEditingStarted”, () => {document.getElementById(“cell_editing”)
.value = “True”
.update()})
grid.addEventListener(“cellEditingStopped”. () => {
    document.getElementById(“cell_editing”)
.value = “False”
.update()

})
})
    return dash_clientside.no_update
}”””,
Output(“grid”, “id”),
Input(“grid”, “id”)

)

Then you need to check the value of the cell_editing in the n_intervals callback, if the value ==“True” then don’t perform the query.

Sorry if there are formatting errors, I typed this all on my phone.

I’m also not 100% sure that this will work exactly as coded, but the mechanism should be correct.

Hi, I tried your way but due to my lack of javascript knowledge can’t troubleshoot it…
just wonder if Output of cleint side callback should be dcc.Input or grid? (tried both anyway)
I tried ask Chat and it gives me a bit different solution but it doesn’t work neither…

clientside_callback(
    """ function (id) {
   dash_ag_grid.getApiAsync(id).then((grid) => {
      grid.addEventListener(“cellEditingStarted”, () => {document.getElementById(“cell-editing”)
.value = “True”
.update()})
grid.addEventListener(“cellEditingStopped”. () => {
    document.getElementById(“cell-editing”)
.value = “False”
.update()

})
})
        return dash_clientside.no_update;
    }""",
    Output("grid", "id"),
    Input("grid", "id")
)

@callback ( Output('grid-invoicing','rowTransaction', allow_duplicate=True),
                 [Input('interval-refresh-invoicing','n_intervals'),
                State('cell-editing', 'value')],
                prevent_initial_call = True)

def update_grid (intervals,cellediting):
    if cellediting == True:
        print('test')
        raise PreventUpdate
    conn = engine.connect()
    df_invoicing_update = pd.read_sql_query(con=conn, sql=sql_query(query))
    conn.close()
    # print(df_invoicing_update.head())
    return( {'update': df_invoicing_update.to_dict('records'),'remove': df_invoicing_update.to_dict('records'),'add': df_invoicing_update.to_dict('records')})
clientside_callback(
    """ function (id) {
   dash_ag_grid.getApiAsync(id).then((grid) => {
      grid.addEventListener(“cellEditingStarted”, () => {document.getElementById(“cell-editing”)
.value = “True”
.update()})
grid.addEventListener(“cellEditingStopped”. () => {
    document.getElementById(“cell-editing”)
.value = “False”
.update()

})
})
        return dash_clientside.no_update;
    }""",
    Output("grid", "id"),
    Input("grid", "id")
)

@callback ( Output('grid-invoicing','rowTransaction', allow_duplicate=True),
                 [Input('interval-refresh-invoicing','n_intervals'),
                State('cell-editing', 'value')],
                prevent_initial_call = True)

def update_grid (intervals,cellediting):
    if cellediting == “True”:
        print('test')
        raise PreventUpdate
    conn = engine.connect()
    df_invoicing_update = pd.read_sql_query(con=conn, sql=sql_query(query))
    conn.close()
    # print(df_invoicing_update.head())
    return( {'update': df_invoicing_update.to_dict('records'),'remove': df_invoicing_update.to_dict('records'),'add': df_invoicing_update.to_dict('records')})

Try this.

Hi jinnyzor,
sorry it doesn’t work, if I understand correctly js function puts into INPUT whatever I write in edited cell.
I made it visible and INPUT takes no value…
btw, You use two different styles of quota marks in your code “ " , does it make any difference?

Here you go:

import dash_ag_grid as dag
from dash import Dash, html, dcc, Input, Output, callback, State, clientside_callback, no_update
import plotly.express as px


app = Dash(__name__)

df = px.data.gapminder()


app.layout = html.Div(
    [
        dcc.Markdown("Example of using `cellValueChanged` in a callback"),
        dcc.Interval(id='test', interval=1000),
        dcc.Input(id='cell-editing'),
        dag.AgGrid(
            id="editing-grid",
            columnDefs=[{"field": i} for i in df.columns],
            rowData=df.to_dict("records"),
            columnSize="sizeToFit",
            defaultColDef={"editable": True, "minWidth": 120},
        ),
        html.Div(id='interval-response')
    ],
    style={"margin": 20},
)

clientside_callback(
    """ function (id) {
       dash_ag_grid.getApiAsync(id).then((grid) => {
            grid.addEventListener("cellEditingStarted", () => {
                document.getElementById("cell-editing").defaultValue = "True"
                document.getElementById("cell-editing").dispatchEvent(new Event("input", { bubbles: true }))
            })
            grid.addEventListener("cellEditingStopped", () => {
                document.getElementById("cell-editing").defaultValue = "False"
                document.getElementById("cell-editing").dispatchEvent(new Event("input", { bubbles: true }))
            })
        })
        return dash_clientside.no_update;
    }""",
    Output("editing-grid", "id"),
    Input("editing-grid", "id")
)

@callback ( Output('interval-response','children', allow_duplicate=True),
                 [Input('test','n_intervals'),
                State('cell-editing', 'value')],
                prevent_initial_call = True)

def update_grid (intervals,cellediting):
    if cellediting == "True":
        print('test')
        return no_update
    return intervals

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

And yes, this does make a difference about the quotes, because they arent valid characters in the code. This is something that phones do when typing.

I fixed the actual code to work, but the mechanism was still the same. :slight_smile:

many Thanks!!!..
works perfectly!!!

2 Likes