Ag Grid: Grid to Grid row dragging of detail rows

I was wondering if it is possible to drag rows from details rows (as defined by detailColumnDefs) to the details of a second grid.

Similar to this example

Dragging Between Grids:

But using master details as shown here:

I tried passing in the rowDrag parameters into the dashGridOptions of the detailCellRendererParams argument, but had no luck :neutral_face:

I shall try getting my non-working example up tomorrow.

import dash_ag_grid as dag
from dash import Dash, html, Input, Output, ClientsideFunction, State, clientside_callback, callback
import random

app = Dash(__name__)

left_data = [
    {
        "id": i + 100,
        "color": "Blue",
        "value1": random.randint(1, 100),
        "value2": random.randint(1, 100),
        "details": [{"detailId": f"{i+100}-detail-{j}", "detailValue": random.randint(1, 100)} for j in range(3)],
    }
    for i in range(5)
]

right_data = [
    {
        "id": i + 200,
        "color": "Green",
        "value1": random.randint(1, 100),
        "value2": random.randint(1, 100),
        "details": [{"detailId": f"{i+200}-detail-{j}", "detailValue": random.randint(1, 100)} for j in range(3)],
    }
    for i in range(5)
]


def master_grid_column_defs():
    return [
        {"field": "id", "cellRenderer": "agGroupCellRenderer"},
        {"field": "color"},
        {"field": "value1"},
        {"field": "value2"},
    ]


def detail_grid_column_defs():
    return [
        {"field": "detailId", "headerName": "Detail ID"},
        {"field": "detailValue", "headerName": "Detail Value"},
    ]


def init_grid(side):
    return dag.AgGrid(
        id=f"row-dragging-grid2grid-simple-{side}",
        masterDetail=True,
        enableEnterpriseModules=True,
        rowData=left_data if side == "left" else right_data,
        columnDefs=master_grid_column_defs(),
        defaultColDef={
            "resizable": True,
            "filter": True,
            "sortable": True,
        },
        columnSize="sizeToFit",
        dashGridOptions={
            "detailRowAutoHeight": True,
            "animateRows": False,
            "pagination": True,
            "rowDragManaged": True,
            "rowDragEntireRow": True,
            "rowDragMultiRow": True,
            "rowSelection": "multiple",
            "suppressMoveWhenRowDragging": True,
        },
        rowClassRules={
            "grid-green-row": 'params.data.color == "Green"',
            "grid-blue-row": 'params.data.color == "Blue"',
        },
        getRowId="params.data.id",
        detailCellRendererParams={
            "detailGridOptions": {
                "columnDefs": detail_grid_column_defs(),
                # TODO: set getRowId="detailId"
                # TODO: set id=f"row-dragging-grid2grid-simple-{side}-detail"
                ## currently get 'ID not found in layout error'
                "id": f"row-dragging-grid2grid-simple-{side}-detail",
                "rowDragManaged": True,
                "rowDragEntireRow": True,
                "rowDragMultiRow": True,
                "rowSelection": "multiple",
                "suppressMoveWhenRowDragging": True,
            },
            "detailColName": "details",
            "suppressCallback": True,
        },
    )


app.layout = html.Div(
    [
        html.Div(
            [
                init_grid("left"),
                init_grid("right"),
            ],
            className="row-dragging-grid-to-grid-container",
        ),
    ]
)

# Set master Grids as dropzone for each other
clientside_callback(
    ClientsideFunction("addDropZone", "dropZoneGrid2GridSimple"),
    Output("row-dragging-grid2grid-simple-left", "id"),
    Input("row-dragging-grid2grid-simple-left", "id"),
    State("row-dragging-grid2grid-simple-right", "id"),
)

# Set detail Grids as dropzone for each other
clientside_callback(
    ClientsideFunction("addDropZone", "dropZoneGrid2GridSimple"),
    Output("row-dragging-grid2grid-simple-left-detail", "id"),
    Input("row-dragging-grid2grid-simple-left-detail", "id"),
    State("row-dragging-grid2grid-simple-right-detail", "id"),
)


if __name__ == "__main__":
    app.run(debug=True)
window.dash_clientside = window.dash_clientside || {};

window.dash_clientside.addDropZone = {
    dropZoneGrid2GridSimple: async function (gridIdLeft, gridIdRight) {
        // Get the grids APIs
        const gridLeftAPI = await dash_ag_grid.getApiAsync(gridIdLeft);
        const gridRightAPI = await dash_ag_grid.getApiAsync(gridIdRight);

        // Get the dropzones parameters from the RIGHT grid
        const gridRightDropZone = gridRightAPI.getRowDropZoneParams();

        // Add RIGHT grid as dropzone of LEFT grid only
        gridLeftAPI.addRowDropZone(gridRightDropZone);

        return window.dash_clientside.no_update;
    },
}

The above example allows you to drag the master rows from one to another (the details are also transferred), however transfer of details from one side to the other (ideally to a different master rows) doesn’t work .

It might suffice to just be able to set the component id (and maybe the rowId) for the details grid, is this possible?

        detailCellRendererParams={
            "detailGridOptions": {
                "columnDefs": detail_grid_column_defs(),
                # TODO: set getRowId="detailId"
                # TODO: set id=f"row-dragging-grid2grid-simple-{side}-detail"
                ## currently get 'ID not found in layout error'
                "id": f"row-dragging-grid2grid-simple-{side}-detail",
                "rowDragManaged": True,
                "rowDragEntireRow": True,
                "rowDragMultiRow": True,
                "rowSelection": "multiple",
                "suppressMoveWhenRowDragging": True,
            },
            "detailColName": "details",
            "suppressCallback": True,
        },

Hi @Redhotmoons

I’m not sure how to do this, but since you have AG Grid Enterprise, you could ask the support team at AG Grid. If you get an example using React, we can help you adapt it for Dash.

Note that AG Grid even offers support during the trial period. Find more info here:

1 Like

Hey :grin:

That’s a good point, I’ll get a React version up :blush:

Best wishes,
Daniel

1 Like