Dash AG Grid Enterprise adds a group of blank rows after editing cell within grid with row groupings

import dash_ag_grid as dag
from dash import Dash, html
from ag_grid_license import license_key
import os


app = Dash(__name__)

data = {
    "Ireland": ["Dublin", "Galway", "Cork"],
    "UK": ["London", "Bristol", "Manchester", "Liverpool"],
    "USA": ["New York", "Boston", "L.A.", "San Fransisco", "Detroit"],
    "MiddleEarth": ["The Shire", "Rohan", "Rivendell", "Mordor"],
    "Midkemia": ["Darkmoor", "Crydee", "Elvandar", "LaMut", "Ylith"],
}

rowData = []
for country, cities in data.items():
    for city in cities:
        rowData.append(
            {
                "country": country,
                "type": "Non Fiction"
                if country in ["Ireland", "UK", "USA"]
                else "Fiction",
                "city": city,
            }
        )




columnDefs = [
    # this column shows just the country group values, but has not group renderer, so there is no expand / collapse functionality
    {
        "headerName": "Country Group - No Renderer",
        "showRowGroup": "country",
        "minWidth": 250,
    },
    # same as before, but we show all group values, again with no cell renderer
    {
        "headerName": "All Groups - No Renderer",
        "showRowGroup": True,
        "minWidth": 240,
    },
    # add in a cell renderer
    {
        "headerName": "Group Renderer A",
        "showRowGroup": True,
        "cellRenderer": "agGroupCellRenderer",
        "minWidth": 220,
    },
    # add in a field
    {
        "headerName": "Group Renderer B",
        "field": "city",
        "showRowGroup": True,
        "cellRenderer": "agGroupCellRenderer",
        "minWidth": 220,
    },
    # add in a cell renderer params
    {
        "headerName": "Group Renderer C",
        "field": "city",
        "minWidth": 240,
        "showRowGroup": True,
        "cellRenderer": "agGroupCellRenderer",
        "cellRendererParams": {
            "suppressCount": True,
            "checkbox": True,
            'innerRenderer': "SimpleCellRenderer",
            "suppressDoubleClickExpand": True,
            "suppressEnterExpand": True,
        },
    },
    {"headerName": "Type", "field": "type", "rowGroup": True},
    {"headerName": "Country", "field": "country", "rowGroup": True},
    {"headerName": "City", "field": "city", "editable": True},
]

app.layout = html.Div(
    [
        dag.AgGrid(
            id="group-cell-renderer-example",
            columnDefs=columnDefs,
            rowData=rowData,
            columnSize="autoSize",
            defaultColDef={"resizable": True},
            enableEnterpriseModules=True,
            licenseKey = license_key,
            dangerously_allow_code=True,
            dashGridOptions={
                "groupSelectsChildren": True,
                "groupDisplayType": "custom",
                "groupDefaultExpanded": 1,
                "rowSelection": "multiple",
            }
        ),
    ],
    style={"margin": 20},
)

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

I am looking to create a row grouped grid that has certain columns which are editable. I took the above row grouping example from the dash ag grid docs and modified it slightly - I set the last field for city as “editable”: True in the column defs. If you run this example and expand any group down to its leaf nodes then try to edit the value to city (to anything), you will see that a set of extra blank rows are added to the grid and grouped together as “Blank (num rows)”

Has anyone encountered and solved this issue?

Upon deeper inspection, after adding a callback for cell change and looking at rowData state, it appears that null (None) rows are created in rowData for each of the blanks in the grid that results from grouping - that is - in the cells underneath the Country Group - No Renderer. Looking at the row counts also confirms this.

I will now search for a workaround

Hi Maclas

Did you find a workaround for this? I am having the same issue

Hello @InspTony,

Welcome to the community!

This should have been fixed in 2.3.0, what version are you running?

1 Like

Thx @jinnyzor I was using 2.0.0 of dash-ag-grid :slight_smile: Update fixed it!

1 Like

Hi I am now having issues with duplicates again.

I have some grouped data and I want to update all rowData once “cellValueChanged” is triggered.

@callback(
    [Output(ag_grid.id, "rowData", allow_duplicate=True)],
    [Input(ag_grid.id, "cellValueChanged")],
    [State(ag_grid.id, "rowData")],
    prevent_initial_call=True,
)
def update(cell_changed, ag_grid_data):
    df = df.dosomething here
    return [df.to_dict("records")]

But I get a duplicate of every row in the ag.grid instead of transformed data. I have checked that the len of df is the same before and after transformation. dash-ag-grid version 2.3.0

Hello @InspTony,

This sounds like you don’t have a getRowId assigned, or you have something that isn’t unique across the board.

Also, why are you doing something like this? The grid shouldn’t be needing to have rowData passed back to it any time you edit it.

I want to trigger a calculation if another row if there is an edit. But I do no have any unique primary key in the datatable, so I am using pandas to query the grid. Since the primary key would be a composite key of multiple columns.

I tried to do a multi-column index df.set_index([col1], [col2], [col3]), but adding this ruined my group by columns in ag grid.

I will try to check if my RowID is undefined.

UPDATE: I had assigned getRowID to the index column that I removed… It works now :slight_smile:

You can set your getRowId to be a combination of multiple columns.

getRowId="`${params.data.col1 || ""}|${params.data.col2 || ""}|${params.data.col3 || ""}`"

This keeps you from having to change anything about your columns and gives you unique identifiers for all your needs.

I use this to be able to push back to multiple sql tables with the different keys from joins. :wink:

1 Like