¿Hay alguna manera de crear dinámicamente zonas de caída? Tengo algunos problemas con ngFor y cdkDropList.

Aquí está mi primera lista y elementos arrastrables:

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

Y aquí está mi segunda lista:

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

Ahora, div con la clase 'conta' está dentro de a * ngFor.

Mi problema es, supongo, con mi segunda lista. Si arrastro un elemento de la segunda lista a la lista uno, funciona normalmente, pero si trato de arrastrar el elemento de la lista uno a cualquier instancia de la lista en la segunda lista, no puedo reconocer que el elemento se está arrastrando. Demostración aquí:

problem demo

¿Estoy haciendo algo mal aquí? La parte mecanografiada está funcionando bien.

Gracias

18
sebamed 10 nov. 2018 a las 15:45

5 respuestas

La mejor respuesta

Después de un día completo de investigación, encontré esta solicitud de extracción en el repositorio Angular CDK en Github. Ahora, como no sabía cómo integrar cdkDropListGroup en mi ejemplo, decidí crear una matriz de ID que se agregarán a [cdkDropListConnectedTo] .

Cada instancia de mi segunda lista habrá generado ID, y esa ID se agregará a la matriz con el prefijo adecuado (en mi segunda lista, en cdkDropList):

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

Método addId :

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

(cdk-drop-list- es un prefijo de ID. CDK coloca este prefijo en cada elemento con el atributo cdkDropList)

Entonces, mi matriz se verá así:

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

Ahora, paso esa matriz a [cdkDropListConnectedTo] en mi primera lista:

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

¡Y funciona perfectamente!

Espero que esto ayude a cualquiera con el mismo problema. Además, eche un vistazo a la solicitud de extracción que mencioné, mi solución es solo una solución, probablemente haya una mejor solución con cdkDropListGroup

22
sebamed 11 nov. 2018 a las 16:07

Con cdkDropListGroup ahora puede hacer:

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

Ya no es necesario cdkDropListConnectedTo en este caso. Ver https://github.com/ angular / material2 / blob / master / src / cdk / drag-drop / drag-drop.md

9
avocadocommander 25 nov. 2018 a las 16:40

También tuve que enfrentar ese problema. Intenté el enfoque de identificación, pero no me sentí demasiado confiado mientras lo usaba. Cuando console.log en esta función addId (), puedo ver la misma identificación repetida varias veces. En lugar de eso, intenté usar el decorador @ViewChildren para tener los componentes de cdkList en tiempo real, y me funciona muy bien.

En mecanografiado

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

En plantilla

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

Creo que puedo mejorarlo mientras cdkDropLists como QueryList tiene propiedades de cambio que un Observable.

1
Benoît Plâtre 7 oct. 2019 a las 01:55

Fuente Enlace

Demo Enlace

Para Listas dinámicas de arrastrar y soltar , podemos usar ID en lugar de # variables de plantilla

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);
    }
  }
}
10
Code Spy 12 abr. 2019 a las 10:15

He creado un ejemplo de stackblitz utilizando un grupo dinámico de listas y cdkDropListGroup . Estoy memorizando el nombre de la primera lista en el elemento de la lista. Al memorizar la primera lista, puedo rastrear qué objetos han cambiado, lo que puede ser útil para construir algunos casos. También me da la posibilidad de cambiar el color de fondo de los elementos que se han movido, mostrando claramente lo que ha cambiado.

0
James D 7 ene. 2020 a las 15:24