Angular 7拖放-动态创建放置区域

时间:2018-11-10 12:45:53

标签: angular drag-and-drop angular7 angular-cdk

是否可以动态创建放置区?我在使用ngFor和cdkDropList时遇到了一些麻烦。

这是我的第一个列表和可拖动元素:

       <div class="subj-container" 
        cdkDropListOrientation="horizontal" 
        cdkDropList 
        #subjectList="cdkDropList"
        [cdkDropListData]="subjects"  
        [cdkDropListConnectedTo]="[lessonList]" 
        (cdkDropListDropped)="drop($event)"
        >
            <div class="subject" *ngFor="let subject of subjects" cdkDrag>
                {{subject.name}}
            </div>
        </div>

这是我的第二个列表:

          <div class="conta" cdkDropList
                #lessonList="cdkDropList"
                [cdkDropListData]="appointment.lessons"
                [cdkDropListConnectedTo]="[subjectList]"
                (cdkDropListDropped)="drop($event)">
                    <div class="sub" cdkDrag *ngFor="let lesson of appointment.lessons">
                        {{lesson.name}}
                </div>
           </div>

现在,类为“ conta”的div位于* ngFor内。

我想,我的问题是我的第二份清单。如果我从第二个列表中拖动一个元素到列表中,它可以正常工作,但是如果我尝试将一个列表中的元素拖动到第二个列表中的列表的任何实例,则无法识别该元素正在被拖动。演示在这里:

problem demo

我在这里做错什么了吗? 打字稿部分工作正常。

谢谢

5 个答案:

答案 0 :(得分:11)

经过一整天的研究,我在Github的Angular CDK存储库中发现了this拉取请求。现在,由于我不知道如何将 cdkDropListGroup 集成到示例中,因此我决定创建一个ID数组,该ID数组将添加到 [cdkDropListConnectedTo] 中。

第二个列表的每个实例都将生成ID,并将该ID添加到具有适当前缀的数组中(在第二个列表中,在cdkDropList上):

<div cdkDropList
      [attr.id]="addId(i, j)"
      [cdkDropListData]="appointment.lessons"
      [cdkDropListConnectedTo]="[subjectList]"
      (cdkDropListDropped)="drop($event)"
>

addId 方法:

addId(i, j) {
    this.LIST_IDS.push('cdk-drop-list-' + i + '' + j);
    return i + '' + j;
}

(cdk-drop-list-是ID前缀。CDK将此前缀放在具有cdkDropList属性的每个元素上)

因此,我的数组将如下所示:

  • cdk-drop-list-00
  • cdk-drop-list-01
  • cdk-drop-list-02

现在,我将该数组传递给我的第一个列表中的 [cdkDropListConnectedTo]

<div class="subj-container" 
    cdkDropListOrientation="horizontal"
    cdkDropList 
    #subjectList="cdkDropList"            
    [cdkDropListData]="subjects" 
    [cdkDropListConnectedTo]="LIST_IDS"
    (cdkDropListDropped)="drop($event)"
>

它完美无瑕!

希望这将帮助任何遇到相同问题的人。另外,看看我提到的拉取请求,我的解决方案只是一种解决方法,使用 cdkDropListGroup

可能有更好的解决方案

答案 1 :(得分:5)

使用cdkDropListGroup,您现在可以执行以下操作:

<div cdkDropListGroup>

  <div cdkDropList
    [cdkDropListData]="data"
    (cdkDropListDropped)="drop($event)">
    <div class="row m-2">
        <div *ngFor="let i of data cdkDrag>{{i}}</div>          
    </div>
  </div>

  <div class="subj-container" 
    cdkDropListOrientation="horizontal"
    cdkDropList 
    #subjectList="cdkDropList"            
    [cdkDropListData]="subjects" 
    (cdkDropListDropped)="drop($event)"> 
  </div>

</div>

在这种情况下,不再需要cdkDropListConnectedTo。 参见https://github.com/angular/material2/blob/master/src/cdk/drag-drop/drag-drop.md

答案 2 :(得分:1)

我也不得不面对这个问题。我尝试了id方法,但使用时并没有感到太大的自信。当我在这个addId()函数中进行console.log时,我可以看到相同的ID重复了几次。 取而代之的是,我尝试使用@ViewChildren装饰器实时获取cdkList组件,并且对我来说效果很好。

在打字稿中

  cdkDropTrackLists: CdkDropList[];
  @ViewChildren(CdkDropList)
  set cdkDropLists(value: QueryList<CdkDropList>) {
    this.cdkDropTrackLists = value.toArray();
  }

在模板中

<div
        cdkDropList
        class="track-list"
        cdkDropListSortingDisabled
        [cdkDropListData]="paragraphIdentifiers"
        (cdkDropListDropped)="drop($event)"
        [cdkDropListConnectedTo]="cdkDropTrackLists">
</div>

我认为我可以改善它,而cdkDropLists作为QueryList则具有可观察到的changes属性。

答案 3 :(得分:0)

来源Link

演示Link

对于动态拖动n拖放列表,我们可以使用ID代替#个模板变量

enter image description here

app.component.html

<div class="col-md-3" *ngFor="let week of weeks">
  <div class="drag-container">
    <div class="section-heading">Week {{week.id}}</div>

    <div cdkDropList id="{{week.id}}" [cdkDropListData]="week.weeklist"
      [cdkDropListConnectedTo]="connectedTo" class="item-list" (cdkDropListDropped)="drop($event)">
      <div class="item-box" *ngFor="let weekItem of week.weeklist" cdkDrag>Week {{week.id}} {{weekItem}}</div>
    </div>
  </div>
</div>

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 {

  weeks = [];
  connectedTo = [];


  constructor() {
    this.weeks = [
      {
        id: 'week-1',
        weeklist: [
          "item 1",
          "item 2",
          "item 3",
          "item 4",
          "item 5"
        ]
      }, {
        id: 'week-2',
        weeklist: [
          "item 1",
          "item 2",
          "item 3",
          "item 4",
          "item 5"
        ]
      }, {
        id: 'week-3',
        weeklist: [
          "item 1",
          "item 2",
          "item 3",
          "item 4",
          "item 5"
        ]
      }, {
        id: 'week-4',
        weeklist: [
          "item 1",
          "item 2",
          "item 3",
          "item 4",
          "item 5"
        ]
      },
    ];
    for (let week of this.weeks) {
      this.connectedTo.push(week.id);
    };
  }

  drop(event: CdkDragDrop<string[]>) {
    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);
    }
  }
}

答案 4 :(得分:0)

有点晚,但很有帮助,值得分享。 我使用角度材质版本10创建了一个看板。 这是演示的链接。 https://stackblitz.com/edit/angular-material-kanban