Question 1
You need to enable row selection for all grids. Currently, it is only available for the grid on the left side. Comment this line of code.
rowSelection={id === 0 ? 'multiple' : undefined}
Same as multiple row selection, change this line
rowSelection={id === 0 ? 'multiple' : undefined}
with this
rowSelection={'multiple'}
Now you can get the selected rows on the right grid like this
rightApi.getSelectedRows()
Question 2
Yes, it is possible. We'll use rightRowData for this purpose. In the example you mentioned, it's not actively used. Let's change our onDragStop method like below
const onDragStop = useCallback(
(params) => {
var data = [...rightRowData];
var nodes = params.nodes;
// allow only if we have 3 rows or less in the right grid
if (data.length < 4) {
if (radioChecked === 0) {
var allowed = 4 - data.length;
leftApi.applyTransaction({
remove: nodes.slice(0, allowed).map(function (node) {
return node.data;
}),
});
} else if (radioChecked === 1) {
leftApi.setNodesSelected({ nodes, newValue: false });
}
nodes.map(function (node) {
if (data.length < 4) {
data.push(node.data);
}
});
}
setRightRowData(data);
},
[leftApi, rightRowData, radioChecked]
);
The code above prevents users drag more than 4 rows. Let's say we have 1 row in the right grid. If a user drags more than 3 rows to the right, only 3 rows are going to be added to the right grid.
We should also set right row data when a user deletes a row from the right grid. Change SportRenderer like the following
const SportRenderer = (props) => {
return (
<i
className="far fa-trash-alt"
style={{ cursor: 'pointer' }}
onClick={() => {
// remove right grid data
var rrd = [...props.rightRowData];
rrd = rrd.filter((d) => d.athlete !== props.node.data.athlete);
props.setRightRowData(rrd);
props.api.applyTransaction({ remove: [props.node.data] });
}}
></i>
);
};
But hey, we need to get our hands on rightRowData and setRightRowData. For that purpose, we move our rightColumns inside GridExample component wrapping it by useMemo and pass rightRowData and setRightRowData as cellRendererParams
const rightColumns = useMemo(
() => [
{
rowDrag: true,
maxWidth: 50,
suppressMenu: true,
rowDragText: (params, dragItemCount) => {
if (dragItemCount > 1) {
return dragItemCount + ' athletes';
}
return params.rowNode.data.athlete;
},
},
{ field: 'athlete' },
{ field: 'sport' },
{
suppressMenu: true,
maxWidth: 50,
cellRenderer: SportRenderer,
// pass rightRowData and setRightRowData as cellRendererParams
cellRendererParams: {
rightRowData: rightRowData,
setRightRowData: setRightRowData,
},
},
],
[rightRowData, setRightRowData]
);
Question 3
Well, I have no idea. It works in my case.
Working plunker: https://plnkr.co/edit/8yKp3eRFm9SiOBnE?preview
UPDATE
Okay, you wanna populate both grids according to your server response. Let's say Michael Phelps is a selected athlete and he exists on the right grid. To do that
const loadGrids = useCallback(() => {
setLeftRowData([...rawData]);
// we manually set here, you can set the selected athletes with your server response just like I did here
setRightRowData([
{
"athlete": "Michael Phelps",
"age": 23,
"country": "United States",
"year": 2008,
"date": "24/08/2008",
"sport": "Swimming",
"gold": 8,
"silver": 0,
"bronze": 0,
"total": 8
}
]);
leftApi.deselectAll();
}, [leftApi, rawData]);
and after my fetch, I manually skip Michael Phelps to prevent keeping it on the left grid because he's a selected athlete
useEffect(() => {
if (!rawData.length) {
fetch('https://www.ag-grid.com/example-assets/olympic-winners.json')
.then((resp) => resp.json())
.then((data) => {
const athletes = [];
let i = 0;
while (athletes.length < 20 && i < data.length) {
var pos = i++;
// skip Michael Phelps
if (athletes.some((rec) => rec.athlete === data[pos].athlete) || data[pos].athlete == "Michael Phelps") {
continue;
}
athletes.push(data[pos]);
}
setRawData(athletes);
});
}
}, [rawData]);