【问题标题】:How to transfer items to new list using Angular DragDrop CDK Service如何使用 Angular DragDrop CDK 服务将项目转移到新列表
【发布时间】:2020-04-11 18:45:20
【问题描述】:

我有一种情况,我需要使用 Angular CDK 提供的DragDrop 服务在我的项目中创建多列表拖放。我能够成功地在其父列表中移动项目,但是当我尝试将该项目转移到新列表时,我发现 _draggables 属性不会更新以将项目转移到新列表。因此,一旦我将项目移动到新列表,我就无法再拖动它。

StackBlitz 问题演示:https://stackblitz.com/edit/angular-kj7y4p

在这个 gif 中,我将 Get To Work 拖到了第二个列表中,但是在将它放到新列表中之后我无法将其拾取。最后,我表明我可以拿起它上面的列表项Get Up(因为那个已经在数组中了)。

我像这样创建每个列表组:

const dropListRef1 = this.dragDrop.createDropList<string[]>(this.dropList1);

const dragListItems1: DragRef<any>[] = [];

this.dragItems1.forEach((item) => {
  let dragRef = this.dragDrop.createDrag(item);
  dragRef.data = item.nativeElement.innerHTML
  dragListItems1.push(dragRef);
})

dropListRef1.data = this.todo

dropListRef1.withItems(dragListItems1);

我通过订阅dropped 来监听丢弃的事件:

dropListRef1.dropped.subscribe((event) => {
  this.drop(event);
})

event 然后用于将项目转移到新数组或在数组中移动项目:

drop(event: any) {
  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);
  }
}

我缺少什么配置才能使其正常工作?谢谢!

编辑:


这就是我使用cdkDrag 服务而不仅仅是指令的原因。

鉴于以下来自我的 api 的数据:

var sections = [
  {
    "uid": "a",
    "order": 0,
    "layout": {
      "rows": [
        {
          "uid": "qz",
          "columns": [
            {
              "uid": "ugjm",
              "size": 6,
              "blocks": [ // NOTE: BLOCK WITH A COLUMN AS PARENT
                {
                  "uid": "bh",
                  "data": {
                    "content": "row qz, column ugjm, block bh"
                  },
                  "type": 2,
                  "order": 0
                }
              ]
            },
            {
              "uid": "plm",
              "size": 6,
              "rows": [ // NOTE: ROW WITH A COLUMN AS PARENT
                {
                  "uid": "bzx",
                  "columns": [
                    {
                      "uid": "1cd",
                      "size":  6,
                      "blocks": [
                        {
                          "uid": "nbv",
                          "data": {
                            "content": "row qz, row bzx, column 1cd, block nbv"
                          }
                        }
                      ]
                    }
                  ]
                }
              ]
            }
          ]
        },
      ],
      "columns": 12
    },
  }
]

我需要在页面上呈现这些行和列,为此,我使用ngTemplateOutlets 在页面上呈现正确的 html 元素:

  <app-kit-section *ngFor="let section of sections" class="kit-section" [data]="section">
    <ng-container *ngIf="section.layout">
        <ng-template [ngTemplateOutlet]="recursiveTmpl" [ngTemplateOutletContext]="{ $implicit: section.layout }"></ng-template>
    </ng-container>
  </app-kit-section>

然后我在这里寻找选择哪个模板:

<ng-template #recursiveTmpl let-element>

  <ng-container *ngIf="element.rows && element.rows.length">
    <ion-row *ngFor="let row of element.rows">
      <ng-template [ngTemplateOutlet]="recursiveTmpl" [ngTemplateOutletContext]="{ $implicit: row }"></ng-template>
    </ion-row>
  </ng-container>

  <ng-container *ngIf="element.columns && element.columns.length">
    <ion-col *ngFor="let column of element.columns">
      <ng-template [ngTemplateOutlet]="recursiveTmpl" [ngTemplateOutletContext]="{ $implicit: column }"></ng-template>
    </ion-col>
  </ng-container>

  <ng-container *ngIf="element.blocks && element.blocks.length">
      <div *ngFor="let block of element.blocks">
        <ng-template [ngTemplateOutlet]="textTpl" [ngTemplateOutletContext]="{ $implicit: block }"></ng-template>
      </div>
  </ng-container>

</ng-template>

这会在页面上呈现各种嵌套的行和列:

这...就是为什么我简化了我的问题以及为什么我需要使用cdkService

【问题讨论】:

  • 尝试使用 ajax 更简洁更容易。
  • Ajax 与这个问题有什么关系?
  • 为什么在 angular-material 提供此功能时使用此自定义逻辑?
  • @GouravGarg 因为在我的实际应用程序中,列表项和下拉列表容器是根据其他一些信息动态添加的,所以我不知道我将拥有多少个下拉列表或列表项运行。它们也是通过 ngTemplateOutlet 呈现的,所以我不能使用 cdkDrag 和 cdkDropList 指令
  • 嗨@JordanLewallen,尝试实现与您相同的功能,但由于CDK拖放方向问题,我被卡住了。你能提供你的解决方案吗?

标签: javascript angular angular-material angular-cdk


【解决方案1】:

根据您的问题,您有动态列表/数据,并且您希望在这些列表之间进行更改。

那么您可以在这些列表之间创建动态 connectedTo。

<div class="example-container" *ngFor="let bucket of buckets">
  <h2>{{bucket.desc}}</h2>

  <div cdkDropList id="{{bucket.id}}" [cdkDropListData]="bucket.items"
      [cdkDropListConnectedTo]="connectedTo" (cdkDropListDropped)="drop($event)">
      <div class="example-box" cdkDrag *ngFor="let item of bucket.items" #dragItem1>{{item}}</div>
  </div>

在你的 ts 文件中

for (let bucket of this.buckets) {
  this.connectedTo.push(bucket.id);
};
this.buckets=[
            {id:'todo',desc:'todo',items:['Get to work','Pick up groceries','Go home','Fall asleep']},
            {id:'done',desc: 'done',items:[Get up','Brush teeth','Take a shower','Check e-mail','Walk dog']}];

这是工作中的 stackblitz link

【讨论】:

  • 这种方法在使用CdkDrag服务时并不能解决问题。在我对您的评论的回复中,cdkDrag 元素在运行时没有嵌套在cdkDropList 中,它们是通过ng-template 动态加载的,我可以添加一个编辑来向您展示我的实际应用程序的外观,我简化了希望得到一个专门用于将项目传输到新数组的修复程序,而不是关于如何重写应用程序其余部分的功能的问题!一秒:)
  • 添加了一个编辑来向您展示我为什么使用 cdkService,希望这对于我简化问题的原因是有意义的 :)
  • 如果有帮助,我也可以试试这个对象
  • 是的,这真的很有帮助!
  • 你能添加这些额外的组件吗?
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2018-03-16
  • 2010-09-10
  • 2021-07-02
  • 2019-09-30
相关资源
最近更新 更多