You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

AgGrid跨表格行拖拽最大行数限制不生效问题排查

问题:AgGrid跨表格拖拽限制行数不生效

我在React项目中使用AgGrid的跨表格拖拽多条记录功能,需求是右侧表格最多只能容纳3行数据。我在onDragStop回调中通过data.length < 4做了行数限制判断,但实际操作后右侧表格仍能显示超过3行的数据。

奇怪的是,点击右侧表格的删除按钮时,表格会自动修正为最多3行(例如显示7行时删除一行后直接变为3行),推测该问题和applyTransaction的使用有关。后续我在代码中添加了applyTransaction的remove操作尝试避免重复行,但问题依旧存在。


表格组件代码

<MyAgGrid
  style={{ height: '100%' }}
  defaultColDef={defaultColDef}
  getRowId={getRowId}
  rowDragManaged={true}
  animateRows={true}
  rowSelection={'multiple'}
  rowDragMultiRow={id === 0}
  suppressRowClickSelection={id === 0}
  suppressMoveWhenRowDragging={id === 0}
  rowData={id === 0 ? leftRowData : rightRowData}
  columnDefs={id === 0 ? leftColumns : rightColumns}
  onGridReady={(params) => onGridReady2(params, id)}
  frameworkComponents={{DeleteRenderer: DeleteRenderer}}
/>

核心业务代码

const [leftApi, setLeftApi] = useState(null);
const [leftColumnApi, setLeftColumnApi] = useState(null);
const [rightApi, setRightApi] = useState(null);
const [rawData, setRawData] = useState([]);
const [leftRowData, setLeftRowData] = useState(null);
const [rightRowData, setRightRowData] = useState([]);
const [radioChecked, setRadioChecked] = useState(0);
const [checkBoxSelected, setCheckBoxSelected] = useState(true);

const DeleteRenderer = (props) => {
    console.log("DeleteRenderer ::::::::::::::: " + props);
    const handleDeleteRow = () => {
        var rrd = [...props.rightRowData];
        rrd = rrd.filter((d) => d.personId !== props.node.data.personId);
        props.setRightRowData(rrd);
        props.api.applyTransaction({ remove: [props.node.data] });
    }
    return (
        <Icon onClick={handleDeleteRow} name="delete" size={15} />
    );
};

const leftColumns = [{
    rowDrag: true,
    maxWidth: 50,
    suppressMenu: true,
    rowDragText: (params, dragItemCount) => {
        if (dragItemCount > 1) {
            return dragItemCount + ' persons';
        }
        return params.rowNode.data.myName;
    },
}, {
    colId: 'checkbox',
    maxWidth: 50,
    checkboxSelection: true,
    suppressMenu: true,
    headerCheckboxSelection: true,
}, {
    field: 'myName'
}, {
    field: 'myEmail'
}, ];

const defaultColDef = {
  flex: 1,
  minWidth: 100,
  sortable: true,
  filter: true,
  resizable: true,
};

const rightColumns = useMemo(
    () => [{
        rowDrag: true,
        maxWidth: 50,
        suppressMenu: true,
        rowDragText: (params, dragItemCount) => {
            if (dragItemCount > 1) {
                return dragItemCount + ' persons';
            }
            return params.rowNode.data.myName;
        },
    }, {
        field: 'myName'
    }, {
        field: 'myEmail'
    }, {
        suppressMenu: true,
        maxWidth: 50,
        cellRenderer: 'DeleteRenderer',
        cellRendererParams: {
            rightRowData: rightRowData,
            setRightRowData: setRightRowData,
        }
    }],
    [rightRowData, setRightRowData]
);

const loadGrids = useCallback(() => {
        setLeftRowData([...rawData]);
        setRightRowData([]);
        leftApi.deselectAll();
    }, [leftApi, rawData]);

useEffect(() => {
    if (rawData.length) {
      loadGrids();
    }
}, [rawData, loadGrids]);

useEffect(() => {
    if (leftColumnApi && leftApi) {
      leftColumnApi.setColumnVisible('checkbox', checkBoxSelected);
      leftApi.setSuppressRowClickSelection(checkBoxSelected);
    }
}, [leftColumnApi, leftApi, checkBoxSelected]);


const frameworkComponents = () => {
        return {DeleteRenderer: DeleteRenderer}
    }

    const getRowId = (params) => {
        return params.data.personId;
    }

    const onDragStop = useCallback(
        (params) => {
            var data = [...rightRowData];
            var nodes = params.nodes;

            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);
                    }
                });
            }

            console.log("::::::::::::::DATA::::::::::::::::" + data);
            setRightRowData(data);
        },
        [leftApi, rightRowData, radioChecked]
    );

useEffect(() => {
    if (!leftApi || !rightApi) {
      return;
    }
    const dropZoneParams = rightApi.getRowDropZoneParams({ onDragStop });

    leftApi.removeRowDropZone(dropZoneParams);
    leftApi.addRowDropZone(dropZoneParams);
}, [leftApi, rightApi, onDragStop]);

const onGridReady2 = (params, side) => {
    if (side === 0) {
      setLeftApi(params.api);
      setLeftColumnApi(params.columnApi);
    }

    if (side === 1) {
      setRightApi(params.api);
    }
};

尝试修复后的onDragStop代码

const onDragStop = useCallback(
            (params) => {
                var data = [...rightRowData];

                var nodes = params.nodes;
                if (data.length < 4) {
                    nodes.map(function(node) {
                        console.log('node', node);
                        console.log('data', data);
                        if (data.length < 4) {
                            if (!data.some((d) => d.contactId === node.data.contactId)) {
                                data.push(node.data);
                            } else {
rightApi.applyTransaction({ remove: [node.data] }); //ADDED
                            }
                        }
                    });
                }
                setRightRowData(data);
            },
            [leftApi, rightRowData/*, radioChecked*/]
        );

内容的提问来源于stack exchange,提问作者copenndthagen

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.14 06:15:58