wake-up-neo.com

Angular 7 Drag & Drop - Erstellen Sie dynamisch Drop-Zones

Gibt es eine Möglichkeit, Drop-Zones dynamisch zu erstellen? Ich habe einige Probleme mit ngFor und cdkDropList.

Hier ist meine erste Liste und ziehbare Elemente:

       <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>

Und hier ist meine zweite Liste:

          <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>

Jetzt befindet sich div mit der Klasse 'conta' in einem * ngFor.

Ich nehme an, mein Problem ist mit meiner zweiten Liste. Wenn ich ein Element aus der zweiten Liste in die erste Liste ziehe, funktioniert es normal. Wenn ich jedoch versuche, ein Element aus der ersten Liste in eine Instanz der zweiten Liste zu ziehen, kann es nicht erkennen, dass das Element gerade gezogen wird. Demo hier:

problem demo

Mache ich hier etwas falsch? Der TypeScript-Teil funktioniert einwandfrei.

Vielen Dank

13
sebamed

Nach einem langen Recherchetag fand ich this pull request auf Angular CDK-Repository auf Github. Nun, da ich nicht wusste, wie man integriert cdkDropListGroup In meinem Beispiel habe ich beschlossen, ein Array von IDs zu erstellen, die zu [cdkDropListConnectedTo] hinzugefügt werden .

Jede Instanz meiner zweiten Liste hat eine ID generiert und diese ID wird dem Array mit einem geeigneten Präfix hinzugefügt (in meiner zweiten Liste auf cdkDropList):

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

addId Methode:

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

(cdk-drop-list- ist ein ID-Präfix. CDK platziert dieses Präfix auf jedem Element mit dem Attribut cdkDropList)

Mein Array sieht also so aus:

  • cdk-drop-list-00
  • cDK-Drop-List-01
  • cDK-Drop-List-02
  • etc.

Jetzt übergebe ich dieses Array an [cdkDropListConnectedTo] in meiner ersten Liste:

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

Und es funktioniert einwandfrei!

Hoffe, dass dies jemandem mit dem gleichen Problem helfen wird. Schauen Sie sich auch die Pull-Anfrage an, die ich erwähnt habe. Meine Lösung ist nur eine Problemumgehung. Es gibt wahrscheinlich eine bessere Lösung mit cdkDropListGroup .

12
sebamed

Mit cdkDropListGroup können Sie jetzt Folgendes tun:

<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>

In diesem Fall ist cdkDropListConnectedTo nicht mehr erforderlich. Siehe https://github.com/angular/material2/blob/master/src/cdk/drag-drop/drag-drop.md

7

Quelle Link

Demo Link

Für dynamische Drag & Drop-Listen können wir ID anstelle von # Vorlagenvariablen verwenden

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
Code Spy