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

Vaadin 14 两个Grid表格之间拖拽功能实现的相关问题咨询

Vaadin Grid 跨组件拖拽实现方案

核心概念解释

  • dragItems就是拖拽操作触发时,你选中的Grid行对应的绑定对象列表,可直接通过拖拽事件的getDraggedItems()方法获取,和你的Grid绑定的实体类泛型一致。

可直接运行的最小实现代码

你可以参考以下完整逻辑替换官方示例的省略部分,解决报错问题:

import com.vaadin.flow.component.grid.Grid;
import com.vaadin.flow.component.orderedlayout.HorizontalLayout;
import com.vaadin.flow.router.Route;
import java.util.ArrayList;
import java.util.List;
import java.util.Optional;

// 自定义绑定的实体类
class SampleItem {
    private String name;
    private int id;

    public SampleItem(int id, String name) {
        this.id = id;
        this.name = name;
    }

    // 必须配置getter、setter,否则Grid无法自动渲染列
    public String getName() { return name; }
    public void setName(String name) { this.name = name; }
    public int getId() { return id; }
    public void setId(int id) { this.id = id; }
}

@Route("grid-drag-demo")
public class GridDragDemoView extends HorizontalLayout {
    // 定义可修改的数据源列表,官方示例省略了这部分
    private final List<SampleItem> sourceList = new ArrayList<>();
    private final List<SampleItem> targetList = new ArrayList<>();

    public GridDragDemoView() {
        setSizeFull();
        // 初始化测试数据
        for (int i = 1; i <= 5; i++) {
            sourceList.add(new SampleItem(i, "源条目" + i));
            targetList.add(new SampleItem(i+10, "目标条目" + i));
        }

        // 1. 配置源Grid:开启拖拽能力
        Grid<SampleItem> sourceGrid = new Grid<>(SampleItem.class);
        sourceGrid.setItems(sourceList);
        sourceGrid.setRowsDraggable(true);
        sourceGrid.setHeightFull();

        // 2. 配置目标Grid:开启放置能力
        Grid<SampleItem> targetGrid = new Grid<>(SampleItem.class);
        targetGrid.setItems(targetList);
        targetGrid.setDropMode(Grid.DropMode.BETWEEN); // 允许放置在两行之间
        targetGrid.setHeightFull();

        // 3. 处理放置逻辑,实现索引计算
        targetGrid.addDropListener(e -> {
            // 获取拖拽的条目(就是你问的dragItems)
            List<SampleItem> dragItems = e.getDraggedItems();
            // 计算放置位置索引
            int insertIndex;
            Optional<SampleItem> targetItem = e.getDropTargetItem();
            if (targetItem.isEmpty()) {
                // 拖拽到Grid空白区域,默认放到列表末尾
                insertIndex = targetList.size();
            } else {
                // 拿到目标行的索引
                insertIndex = targetList.indexOf(targetItem.get());
                // 如果是放在目标行的下方,索引加1
                if (e.getDropLocation() == Grid.DropLocation.AFTER) {
                    insertIndex++;
                }
            }

            // 同步两个列表的数据
            sourceList.removeAll(dragItems);
            targetList.addAll(insertIndex, dragItems);

            // 刷新Grid显示
            sourceGrid.getDataProvider().refreshAll();
            targetGrid.getDataProvider().refreshAll();
        });

        add(sourceGrid, targetGrid);
    }
}

常见报错解决

  • 官方示例省略了数据源初始化逻辑,直接用不可变集合作为Grid数据源会抛出修改异常,必须用ArrayList这类可修改的集合。
  • 实体类没有写getter/setter会导致Grid无法渲染列,出现空白或者报错。
  • Grid没有设置明确高度会导致拖拽事件不触发,建议用setHeightFull()或者指定固定像素高度。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.03 13:24:07