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

Angular 14中PrimeNg DragDrop如何实现节点拖拽复制而非移动

实现PrimeNg Tree跨树拖拽保留原节点

要实现跨树拖拽时保留左侧树的节点,核心是把默认的移动操作改成复制操作,具体可以通过以下步骤实现:

1. 配置拖拽作用域

确保左右两棵树的dragDropScope属性设置为相同值(比如shared),这样PrimeNg会允许它们之间的拖拽交互:

<div class="grid">
  <div class="col-6">
    <p-tree 
      [value]="leftNodes" 
      draggableNodes="true" 
      droppableNodes="true" 
      dragDropScope="shared"
    ></p-tree>
  </div>
  <div class="col-6">
    <p-tree 
      [value]="rightNodes" 
      draggableNodes="true" 
      droppableNodes="true" 
      dragDropScope="shared"
      (onNodeDrop)="onNodeDrop($event)"
    ></p-tree>
  </div>
</div>

2. 处理拖拽完成事件,实现节点复制

在右侧树的onNodeDrop事件中,我们需要克隆拖拽的节点并添加到目标树,同时阻止默认的移动行为(避免左侧节点被移除):

import { TreeNode } from 'primeng/api';

export class YourComponent {
  leftNodes: TreeNode[] = [
    // 左侧树节点数据示例
    {
      label: "Documents",
      children: [
        { label: "Work", children: [{ label: "Expenses.doc" }, { label: "Resume.doc" }] },
        { label: "Home", children: [{ label: "Invoices.txt" }] }
      ]
    }
  ];

  rightNodes: TreeNode[] = [];

  onNodeDrop(event: any) {
    // 1. 克隆拖拽的节点(深拷贝避免引用关联问题)
    const draggedNode = event.dragNode;
    // 简单深拷贝方式,复杂节点结构建议用lodash.cloneDeep
    const clonedNode = JSON.parse(JSON.stringify(draggedNode));

    // 2. 将克隆节点添加到目标位置
    if (event.dropNode) {
      // 拖到某个节点内部,作为子节点
      if (!event.dropNode.children) {
        event.dropNode.children = [];
      }
      event.dropNode.children.push(clonedNode);
    } else {
      // 拖到根节点层级
      this.rightNodes.push(clonedNode);
    }

    // 3. 阻止默认移动操作,保留左侧原节点
    event.reject();
  }
}

关键说明

  • 节点克隆:必须使用深拷贝,否则只是复制引用,修改目标树节点会同步影响原树节点。如果你的节点包含函数、特殊对象等复杂结构,推荐使用lodash.cloneDeep替代JSON.parse(JSON.stringify())。
  • event.reject():这个方法会取消PrimeNg默认的拖拽移动逻辑,让左侧树的数据源保持不变。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.08 21:10:28