【问题标题】:DOM Exception in angular 8 Drag and Drop CDK角度 8 拖放 CDK 中的 DOM 异常
【发布时间】:2019-11-05 06:58:32
【问题描述】:

我正在使用 Angular CDK 创建一个简单的 Angular 拖放应用程序。我只想拖我的 盒子并将其放到另一个盒子中。但是当释放拖放区域内的拖动框时,我得到了错误。请帮助修复它。

我遇到的错误

Unhandled Promise rejection: Failed to execute 'appendChild' on 'Node': The new child element contains the parent. ; Zone: <root> ; Task: Promise.then ; Value: DOMException: Failed to execute 'appendChild' on 'Node': The new child element contains the parent.
    at DragRef._cleanupDragArtifacts (http://localhost:4200/vendor.js:1615:121)
    at http://localhost:4200/vendor.js:1471:22
    at ZoneDelegate.invoke (http://localhost:4200/polyfills.js:3365:26)
    at Zone.run (http://localhost:4200/polyfills.js:3130:43)
    at http://localhost:4200/polyfills.js:3861:36
    at ZoneDelegate.invokeTask (http://localhost:4200/polyfills.js:3397:31)
    at Zone.runTask (http://localhost:4200/polyfills.js:3174:47)
    at drainMicroTaskQueue (http://localhost:4200/polyfills.js:3565:35)
    at ZoneTask.invokeTask [as invoke] (http://localhost:4200/polyfills.js:3475:21)
    at invokeTask (http://localhost:4200/polyfills.js:4609:14) Error: Failed to execute 'appendChild' on 'Node': The new child element contains the parent.
    at DragRef._cleanupDragArtifacts (http://localhost:4200/vendor.js:1615:121)
    at http://localhost:4200/vendor.js:1471:22
    at ZoneDelegate.invoke (http://localhost:4200/polyfills.js:3365:26)
    at Zone.run (http://localhost:4200/polyfills.js:3130:43)
    at http://localhost:4200/polyfills.js:3861:36
    at ZoneDelegate.invokeTask (http://localhost:4200/polyfills.js:3397:31)
    at Zone.runTask (http://localhost:4200/polyfills.js:3174:47)
    at drainMicroTaskQueue (http://localhost:4200/polyfills.js:3565:35)
    at ZoneTask.invokeTask [as invoke] (http://localhost:4200/polyfills.js:3475:21)
    at invokeTask (http://localhost:4200/polyfills.js:4609:14)
api.onUnhandledError @ zone-evergreen.js:651
handleUnhandledRejection @ zone-evergreen.js:675
api.microtaskDrainDone @ zone-evergreen.js:668
drainMicroTaskQueue @ zone-evergreen.js:566
invokeTask @ zone-evergreen.js:469
invokeTask @ zone-evergreen.js:1603
globalZoneAwareCallback @ zone-evergreen.js:1629

我会在下面粘贴我的代码

我的 app.component.html

<section>
  <div class="wrapper">
    <div class="outerBox">
        <div class="innerBox" cdkDropList [cdkDropListConnectedTo]="[dropZone]" cdkDrag></div>
    </div>

    <div class="outerBox" #dropZone="cdkDropList" cdkDropList (cdkDropListDropped)="onItemDrop($event)">
    </div>
  </div>
</section>

和 app.component.ts

import { Component } from '@angular/core';
import {CdkDragDrop, moveItemInArray, transferArrayItem} from '@angular/cdk/drag-drop';
@Component({
  selector: 'app-root',
  templateUrl: './app.component.html',
  styleUrls: ['./app.component.css']
})
export class AppComponent {

  onItemDrop(event) {
    console.log(event);
  }
}

app.component.css 文件看起来像

.wrapper {
    display: flex;
}
.outerBox {
    width: 300px;
    height: 500px;
    border: 1px solid #333;
    padding: 10px;
    margin: 10px;
}
.innerBox {
    width: 100px;
    height: 100px;
    background: skyblue;
}

请帮助解决错误。

提前致谢。

【问题讨论】:

标签: javascript angular drag-and-drop angular-material angular-cdk


【解决方案1】:

您需要在 .ts 文件中定义单独的列表来存储数据,例如

  list1 = ['hello1'];
  list2 = [];

onItemDrop 函数的.ts 文件中,您还需要提供用于传输数据的代码:

if (event.previousContainer === event.container) {
    moveItemInArray(event.container.data, event.previousIndex, event.currentIndex);
} else {
    transferArrayItem(
        event.previousContainer.data,
        event.container.data,
        event.previousIndex,
        event.currentIndex
    );
}

那么此代码将在您的 .html 文件中运行:

<section>
    <div class="wrapper">
      <div class="outerBox" [cdkDropListData]="list1" id="dropZone1" cdkDropList [cdkDropListConnectedTo]="'dropZone2'" (cdkDropListDropped)="onItemDrop($event)">
          <div *ngFor="let item of list1" class="innerBox" cdkDrag></div>
      </div>
      <div class="outerBox" [cdkDropListData]="list2" id="dropZone2" [cdkDropListConnectedTo]="'dropZone1'" cdkDropList (cdkDropListDropped)="onItemDrop($event)">
        <div *ngFor="let item of list2" class="innerBox" cdkDrag></div>
      </div>
    </div>
</section>

在上面的 HTML 中,我修复了以下内容:

  • 将 cdkDropList 与 cdkDrag 元素分开。
  • 正确指定连接的 ID。
  • 使用 *ngFor 迭代要显示的数据。

【讨论】:

    【解决方案2】:

    您可以按照以下步骤开始操作。

    在组件类中

    1. 定义两个列表以相互连接。
    2. 并实现 moveItemInArraytransferArrayItem cdk 辅助方法:第一种方法是处理每个列表中的更改索引。第二个处理从列表到另一个列表的传输。

    在模板中:

    1. 将每个列表绑定到引用或 ID(例如 #listRef)容器
    2. 为每个指令添加 cdkDropListcdkDropListDatacdkDropListConnectedTo 指令
    3. 为两个列表添加cdkDropListDropped时监听的方法,此处为“onItemDrop”
    4. 迭代在每个列表上使用 cdkDrag 指令在每个可拖动项目上

    我准备了一个有效的堆栈闪电战example

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2021-05-22
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多