Updating Data

Transaction Updates allow large numbers of rows in the grid to be added, removed or updated in an efficient manner. Use Transaction Updates for fast changes to large datasets.

rowTransaction - Updates row data. Pass a transaction object with lists for add, remove and update.

Identifying Rows for Update and Remove

In order to update, add or remove data with rowTransaction the data must have a Row ID.
If you are providing Row IDs using getRowId() then the grid will match data provided in the transaction with data in the grid using the key.

Row IDs must be unique and not editable. See the Row IDs page for more information.

For updating rows, the grid will find the row with the same key and then swap the data out for the newly provided data.

For removing rows, the grid will find the row with the same key and remove it. For this reason, the provided records within the remove array only need to have a key present.

rowTransaction = {
  "add": [
      # adding a row, there should be no row with ID = 4 already
      {"employeeId": "4", "name": "Billy", "age": 55}
  ],

  "update": [
      # updating a row, the grid will look for the row with ID = 2 to update
      {"employeeId": "2", name: "Bob", "age": 23}
  ],

  "remove": [
      # deleting a row, only the ID is needed, other attributes (name, age) don't serve any purpose
      {"employeeId": "5"}
  ]
}

Updating with rowTransaction and rowData

The example updates data in different ways:

import dash_ag_grid as dag
from dash import Dash, html, dcc, Input, Output, State, ctx, no_update, callback

app = Dash(__name__)


rowData = [
    {"make": "Toyota", "model": "Celica", "price": 35000},
    {"make": "Ford", "model": "Mondeo", "price": 32000},
    {"make": "Porsche", "model": "Boxster", "price": 72000},
]

columnDefs = [
    {
        "headerName": "id",
        "valueGetter": {"function": "params.node.id"},
        "checkboxSelection": True,
    },
    {"field": "make"},
    {"field": "model"},
    {
        "field": "price",
        "cellRenderer": "agAnimateShowChangeCellRenderer",
    },
]

app.layout = html.Div(
    [
        html.Button("Update selected", id="transactions-update"),
        html.Button("Remove Selected", id="transactions-remove"),
        html.Button("Add Rows", id="transactions-add"),
        html.Button("Clear", id="transactions-clear"),
        html.Button("Start Over", id="transactions-start"),
        dag.AgGrid(
            id="transactions-grid",
            rowData=rowData,
            columnDefs=columnDefs,
            defaultColDef={"flex": 1},
            dashGridOptions={"rowSelection": "multiple"},
            getRowId="params.data.make",
        ),
    ],
)


@callback(
    Output("transactions-grid", "rowData"),
    Input("transactions-clear", "n_clicks"),
    Input("transactions-start", "n_clicks"),
)
def update_rowdata(*_):
    if ctx.triggered_id == "transactions-clear":
        return []
    return rowData


@callback(
    Output("transactions-grid", "rowTransaction"),
    Input("transactions-remove", "n_clicks"),
    Input("transactions-update", "n_clicks"),
    Input("transactions-add", "n_clicks"),
    State("transactions-grid", "selectedRows"),
)
def update_rowdata(n1, n2, n3, selection):

    if ctx.triggered_id == "transactions-remove":
        if selection is None:
            return no_update
        return {"remove": selection}

    if ctx.triggered_id == "transactions-update":
        if selection is None:
            return no_update
        for row in selection:
            row["price"] = row["price"] + n2
        return {"update": selection}

    if ctx.triggered_id == "transactions-add":
        newRows = [row.copy() for row in rowData]
        for row in newRows:
            row["make"] = row["make"] + str(n3)
        return {"add": newRows}


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

Adding Pre-selected Rows

In this example, note the following:
- Row ids are set with getRowId(params.data.id)
- The ids are generated from the n_clicks counter, so they are unique
- The "id" column is hidden by setting {"hide": True} in the columnDefs
- The new rows are automatically selected.

import dash_ag_grid as dag
from dash import Dash, dcc, html, Input, Output, State, callback

app = Dash(__name__)

random_names = [
    "Jane",
    "Joe",
    "Alex",
    "Victor",
    "Claire",
    "Clark",
    "Tim",
    "Tania",
]

data = [{"id": str(i), "name": random_names[i], "number": str(i)} for i in range(3)]

columnDefs = [
    {"field": "id", "hide": True},
    {"field": "name", "checkboxSelection": True, "headerCheckboxSelection": True},
    {"field": "number"},
]

app.layout = html.Div(
    [
        dcc.Markdown("Example of adding pre-selected rows"),
        html.Button("Add row", id="transactions2-add", n_clicks=2),
        dag.AgGrid(
            id="transactions2-grid",
            columnDefs=columnDefs,
            rowData=data,
            columnSize="sizeToFit",
            dashGridOptions={"rowSelection": "multiple"},
            getRowId="params.data.id",
        ),
        html.Div(id="transactions2"),
    ],
    style={"margin": 20},
)


@callback(
    Output("transactions2-grid", "rowTransaction"),
    Output("transactions2-grid", "selectedRows"),
    Input("transactions2-add", "n_clicks"),
    State("transactions2-grid", "selectedRows"),
    prevent_initial_call=True,
)
def new_and_selected(n, selected):
    new_row = [{"id": str(n), "name": random_names[n % 8], "number": str(n)}]
    selected = selected + new_row if selected else new_row
    return {"add": new_row, "async": False}, selected


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

Example of adding pre-selected rows