@alistair.welch,
Here is a working example of how to do this without any additional options from the grid:
import dash_ag_grid as dag
import pandas as pd
from dash import Dash, html, Output, Input, dcc
app = Dash(__name__)
df = pd.read_csv(
"https://raw.githubusercontent.com/plotly/datasets/master/ag-grid/olympic-winners.csv"
)
columnDefs = [
{"field": "country", "dndSource": True},
{"field": "year"},
{"field": "sport"},
{"field": "gold"},
{"field": "silver"},
{"field": "bronze"},
]
app.layout = html.Div(
[
dag.AgGrid(
columnDefs=columnDefs,
rowData=df.to_dict("records")[:5],
columnSize="sizeToFit",
defaultColDef={"resizable": True, "sortable": True, "filter": True},
dashGridOptions={"rowDragManaged": True, "animateRows": True},
style={'width': '45%'},
id='grid1'
),
dag.AgGrid(
columnDefs=columnDefs,
rowData=df.to_dict("records")[6:10],
columnSize="sizeToFit",
defaultColDef={"resizable": True, "sortable": True, "filter": True},
dashGridOptions={"rowDragManaged": True},
style={'width': '45%'},
id='grid2'
),
html.Button(id='drop1', style={'display':'none'}, n_clicks=0),
html.Button(id='drop2', style={'display':'none'}, n_clicks=0),
dcc.Store(id='dropStore', storage_type='session')
],
style={"margin": 20, "display": "flex"},
)
## enable drag-n-drop
app.clientside_callback(
"""
function (p) {
const mouseClickEvents = ['mousedown', 'click', 'mouseup'];
function simulateMouseClick(element, args) {
mouseClickEvents.forEach((mouseEventType) =>
element.dispatchEvent(
new MouseEvent(mouseEventType, {
view: window,
bubbles: true,
cancelable: true,
buttons: 1,
target: element,
...args,
})
)
);
mouseClickEvents.forEach((mouseEventType) =>
element.dispatchEvent(
new PointerEvent(mouseEventType, {
view: window,
bubbles: true,
cancelable: true,
buttons: 1,
target: element,
...args,
})
)
);
}
var gridOrigin;
var gridDragOver = (event) => {
const dragSupported = event.dataTransfer.types.length;
if (dragSupported) {
event.dataTransfer.dropEffect = 'copy';
event.preventDefault();
}
};
var gridDragStart = (origin, event) => {
gridOrigin = origin
}
var gridDrop = (target, event) => {
event.preventDefault();
const jsonData = event.dataTransfer.getData('application/json');
const data = JSON.parse(jsonData);
// if data missing or the drop target is the same as the origin, do nothing
if (!data || target == gridOrigin) {
return;
}
// store data for use in transfer
sessionStorage.setItem('dropStore', jsonData)
if (target == 'grid2') {
simulateMouseClick(document.querySelector('#drop2'))
} else {
simulateMouseClick(document.querySelector('#drop1'))
}
};
setTimeout(() => {
document.querySelector('#grid1').addEventListener('dragstart', (event)=>gridDragStart('grid1', event))
document.querySelector('#grid2').addEventListener('dragstart', (event)=>gridDragStart('grid2', event))
document.querySelector('#grid1').addEventListener('dragover', gridDragOver)
document.querySelector('#grid2').addEventListener('dragover', gridDragOver)
document.querySelector('#grid2').addEventListener('drop', (event)=>gridDrop('grid2', event))
document.querySelector('#grid1').addEventListener('drop', (event)=>gridDrop('grid1', event))
}, 500)
return window.dash_clientside.no_update
}
""",
Output('grid2', 'id'),
Input('grid2', 'id')
)
app.clientside_callback(
"""
function (n) {
data = JSON.parse(sessionStorage.getItem('dropStore'))
//remove stored session data
sessionStorage.setItem('dropStore', null)
return {'add': [data]}
}
""",
Output('grid2', 'rowTransaction'),
Input('drop2', 'n_clicks'),
prevent_initial_call=True
)
app.clientside_callback(
"""
function (n) {
data = JSON.parse(sessionStorage.getItem('dropStore'))
//remove stored session data
sessionStorage.setItem('dropStore', null)
return {'add': [data]}
}
""",
Output('grid1', 'rowTransaction'),
Input('drop1', 'n_clicks'),
prevent_initial_call=True
)
if __name__ == "__main__":
app.run_server(debug=True, port=1234)