plotly / dash-ag-grid

Dash AG Grid is a high-performance and highly customizable component that wraps AG Grid, designed for creating rich datagrids.
https://dash.plotly.com/dash-ag-grid
MIT License
175 stars 25 forks source link

[BUG] Adding row through rowTransaction creates multiple duplicate rows #263

Closed yxc8 closed 6 months ago

yxc8 commented 9 months ago

Only modifying the newRows parameter from official example code reproduces this error. When Add Row is clicked once, it adds one empty row, no problem. When you click again, it adds two more empty rows, now I have three empty rows. Click again now adds three more empty rows and I end up with six empty rows..

from dash import Dash, html, Input, Output, State, ctx, no_update, callback

app = Dash(__name__)

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

columnDefs = [
    {"field": "id", "checkboxSelection": True, "headerCheckboxSelection": True},
    {"field": "make"},
    {"field": "model"},
    {"field": "price", "cellRenderer": "agAnimateShowChangeCellRenderer", },
]

app.layout = html.Div(
    [
        html.Button("Add Row", id="btn-client-side-transaction-add"),
        html.Button("Add Rows at index 2", id="btn-client-side-transaction-add-index-2"),
        html.Button("Update selected", id="btn-client-side-transaction-update"),
        html.Button("Remove Selected", id="btn-client-side-transaction-remove"),
        html.Button("Clear", id="btn-client-side-transaction-clear"),
        html.Button("Start Over", id="btn-client-side-transaction-start"),
        dag.AgGrid(
            id="client-side-transaction",
            rowData=rowData,
            columnDefs=columnDefs,
            columnSize="sizeToFit",
            dashGridOptions={"rowSelection": "multiple", 'animateRows': True},
            getRowId="params.data.id"
        ),
    ],
)

@callback(
    Output("client-side-transaction", "rowData"),
    Input("btn-client-side-transaction-clear", "n_clicks"),
    Input("btn-client-side-transaction-start", "n_clicks"),
)
def update_rowdata(*_):
    return [] if ctx.triggered_id == "btn-client-side-transaction-clear" else rowData

@callback(
    Output("client-side-transaction", "rowTransaction"),
    Input("btn-client-side-transaction-add", "n_clicks"),
    Input("btn-client-side-transaction-add-index-2", "n_clicks"),
    Input("btn-client-side-transaction-update", "n_clicks"),
    Input("btn-client-side-transaction-remove", "n_clicks"),
    State("client-side-transaction", "selectedRows"),
    prevent_initial_call=True,
)
def update_transaction(n1, n2, n3, n4, selection):
    if ctx.triggered_id in ["btn-client-side-transaction-add", "btn-client-side-transaction-add-index-2"]:
        newRows = [
            {
                "id": None,
                "make": None, "model": None, "price": None
            }
        ]
        print(newRows)
        return (
            {"add": newRows}
            if ctx.triggered_id == "btn-client-side-transaction-add"
            else {"add": newRows, 'addIndex': 2}
        )

    if selection:
        if ctx.triggered_id == "btn-client-side-transaction-update":
            for row in selection:
                row["price"] = row["price"] + n3
            return {"update": selection}

        if ctx.triggered_id == "btn-client-side-transaction-remove":
            return {"remove": selection}

    # If no rows selected, no grid update
    return no_update

if __name__ == "__main__":
    app.run(debug=True)
BSd3v commented 9 months ago

Hello @yxc8,

I am pretty sure this is a glitch due to not passing an id for the grid to determine the value.