web-dev-qa-db-fra.com

Angular 7 Drag and Drop - Création dynamique de zones de dépôt

Existe-t-il un moyen de créer dynamiquement des zones de dépôt? J'ai des problèmes avec ngFor et cdkDropList.

Voici ma première liste d'éléments glissables:

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

Et voici ma deuxième 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>

Maintenant, div avec la classe 'conta' est à l'intérieur d'un * ngFor.

Mon problème est, je suppose, avec ma deuxième liste. Si je déplace un élément de la deuxième liste vers la liste, cela fonctionne normalement, mais si j'essaie de faire glisser un élément de la liste un vers une occurrence de la liste dans la deuxième liste, il ne peut pas reconnaître que l'élément est déplacé. Démo ici:

problem demo

Est-ce que je fais quelque chose de mal ici? La partie TypeScript fonctionne bien.

Merci

13
sebamed

Après une journée complète de recherche, j’ai trouvé cette demande de tirage sur Angular CDK référentiel sur Github. Maintenant, je ne savais pas comment intégrer cdkDropListGroup Dans mon exemple, j'ai décidé de créer un tableau d'identifiants qui seront ajoutés à [cdkDropListConnectedTo] .

Chaque instance de ma deuxième liste aura généré un ID, et cet ID sera ajouté au tableau avec le préfixe approprié (dans ma deuxième liste, sur cdkDropList):

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

addId méthode:

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

[cdk-drop-list- est un préfixe ID. CDK place ce préfixe sur chaque élément avec l'attribut cdkDropList)]

Donc, mon tableau va ressembler à:

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

Maintenant, je passe ce tableau à [cdkDropListConnectedTo] dans ma première liste:

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

Et cela fonctionne parfaitement!

J'espère que cela aidera tout le monde avec le même problème. En outre, jetez un coup d'œil à la demande d'extraction que j'ai mentionnée, ma solution n'est qu'un moyen de contournement. Il existe probablement une meilleure solution avec cdkDropListGroup

12
sebamed

Avec cdkDropListGroup, vous pouvez maintenant faire:

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

Plus besoin de cdkDropListConnectedTo dans ce cas. Voir https://github.com/angular/material2/blob/master/src/cdk/drag-drop/drag-drop.md

7
avocadocommander

Source Lien

Démo Lien

Pour glisser-déposer dynamiques , nous pouvons utiliser un ID au lieu de # Variables de modèle

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