Brandon Michael Hunter
Brandon Michael Hunter

Reputation: 1221

Angular Drag and Drop - can't drop items to the target location

I'm having a problem with the my Angular 9 project where the drag and drop functionality doesn't work consistently. Whenever I try to drag an object to its destination location, the drop never completes. Most of the time the object returns back to its original location or it moves to another position either before or after the target position where I want to move the object to. Here is my code:

<div class="col-sm-12">

          <div cdkDropList class="example-list cdk-drop-list-receiving" (cdkDropListDropped)="drop($event)">
            <ng-container *ngFor="let word of Words; let i = index;">
                <div class="row" *ngIf="((i % 2) == 0)"  style="margin-right: 0px; margin-left: 0px;" >
                  <div class="col-sm-1 text-center" style="padding: 20px 10px; border: 1px solid black"> {{ i }}</div>
                  <div class="col-sm-5 text-center example-box"  style="border: 1px solid black" cdkDrag ><div class="example-custom-placeholder" *cdkDragPlaceholder></div>{{ Words[i].Title }}</div>
                  <div class="col-sm-1 text-center" style="padding: 20px 10px; border: 1px solid black"> {{ i+1 }}</div>
                  <div class="col-sm-5 text-center example-box" *ngIf="Words[i+1] !== undefined" style="border: 1px solid black" cdkDrag ><div class="example-custom-placeholder" *cdkDragPlaceholder></div>{{ Words[i+1].Title }}</div>
                </div>

            </ng-container>
          </div> 
        </div>

Here is a link to the app live so you can visualize the issues that I'm seeing: [UPDATE] https://stackblitz.com/edit/drag-and-drop-issue

Thank you in advance

Upvotes: 0

Views: 4534

Answers (1)

Aakash Garg
Aakash Garg

Reputation: 10979

Cdk drop list either work vertically or horizontally. In your code indexes were messed up. What you really needed was a CdkDropListGroup to let it operate both way. I have created an code for same with your layout. I have made the same array behave like two different cdkdroplist inside same cdkDropListGroup.

Working Stackblitz :- https://stackblitz.com/edit/drag-and-drop-issue-gw4epd

HTML

<div cdkDropListGroup class="row example-list cdk-drop-list-receiving">
    <div class="row">
        <div class="col-6 group" cdkDropList id="listOne" (cdkDropListDropped)="drop($event)" [cdkDropListConnectedTo]="['listTwo']">
            <ng-container *ngFor="let word of Words; let i=index">
                <div *ngIf="(i%2)==0" class="row" style="margin-right: 0px; margin-left: 0px;">
                    <div class="col-sm-2 text-center" style="padding: 20px 10px; border: 1px solid black"> {{ i }}
                    </div>
                    <div class="col-sm-10 text-center example-box" style="border: 1px solid black" cdkDrag>
                        <div class="example-custom-placeholder col-sm-10" *cdkDragPlaceholder></div>
                        {{ Words[i].Title }}
                    </div>
                </div>
            </ng-container>
        </div>
        <div class="col-6 group" cdkDropList id="listTwo" (cdkDropListDropped)="drop($event)" [cdkDropListConnectedTo]="['listOne']">
            <ng-container *ngFor="let word of Words; let i=index">
                <div *ngIf="(i%2)!==0" class="row" style="margin-right: 0px; margin-left: 0px;">
                    <div class="col-sm-2 text-center" style="padding: 20px 10px; border: 1px solid black"> {{ i }}
                    </div>
                    <div class="col-sm-10 text-center example-box" style="border: 1px solid black" cdkDrag>
                        <div class="example-custom-placeholder col-sm-10" *cdkDragPlaceholder></div>
                        {{ Words[i].Title }}
                    </div>
                </div>
            </ng-container>
        </div>
    </div>
</div>



<!-- Copyright 2019 Google LLC. All Rights Reserved.
    Use of this source code is governed by an MIT-style license that
    can be found in the LICENSE file at http://angular.io/license -->

TS :-

import {Component} from '@angular/core';
import {CdkDragDrop, moveItemInArray} from '@angular/cdk/drag-drop';

/**
 * @title Drag&Drop custom placeholder
 */
@Component({
  selector: 'cdk-drag-drop-custom-placeholder-example',
  templateUrl: 'cdk-drag-drop-custom-placeholder-example.html',
  styleUrls: ['cdk-drag-drop-custom-placeholder-example.css'],
})
export class CdkDragDropCustomPlaceholderExample {
  Words = [
    {Title: 'Test A'},
    {Title: 'Test B'},
    {Title: 'Test C'},
    {Title: 'Test D'},
    {Title: 'Test E'},
    {Title: 'Test F'},
    {Title: 'Test G'},
    {Title: 'Test H'},
    {Title: 'Test I'},
    {Title: 'Test J'},
    {Title: 'Test K'},
    {Title: 'Test L'},
    {Title: 'Test M'},
    {Title: 'Test N'},
    {Title: 'Test O'}

  ];

  drop(event: CdkDragDrop<string[]>) {
    console.log(event);
    if (event.previousContainer === event.container) {
      console.log("same Container");
      if(event.previousContainer.id === 'listOne'){
        moveItemInArray(this.Words, event.previousIndex*2, event.currentIndex*2);
      } else {
        moveItemInArray(this.Words, (event.previousIndex*2)+1, (event.currentIndex*2)+1)
      }
    } else {
      console.log("different Container");
      var connectedTo = event.previousContainer.connectedTo.toString();
      console.log(connectedTo)
      if(connectedTo ==='listOne') {
        console.log('list2');
        moveItemInArray(this.Words, (event.previousIndex*2)+1, (event.currentIndex*2));
      } else {
        console.log('list1');
        moveItemInArray(this.Words, (event.previousIndex*2), (event.currentIndex*2)+1);
      }
    }
  }
}


/**  Copyright 2019 Google LLC. All Rights Reserved.
    Use of this source code is governed by an MIT-style license that
    can be found in the LICENSE file at http://angular.io/license */

CSS :-

.example-list {
  width: 500px;
  max-width: 100%;
  border: solid 1px #ccc;
  min-height: 60px;
  display: block;
  background: white;
  border-radius: 4px;
  overflow: hidden;
}

.group{
  padding: 0;
  margin: 0;
}

.example-box {
  padding: 20px 10px;
  border-bottom: solid 1px #ccc;
  color: rgba(0, 0, 0, 0.87);
  display: flex;
  flex-direction: row;
  align-items: center;
  justify-content: space-between;
  box-sizing: border-box;
  cursor: move;
  background: white;
  font-size: 14px;
}

.cdk-drag-preview {
  box-sizing: border-box;
  border-radius: 4px;
  box-shadow: 0 5px 5px -3px rgba(0, 0, 0, 0.2),
              0 8px 10px 1px rgba(0, 0, 0, 0.14),
              0 3px 14px 2px rgba(0, 0, 0, 0.12);
}

.cdk-drag-animating {
  transition: transform 250ms cubic-bezier(0, 0, 0.2, 1);
}

.example-box:last-child {
  border: none;
}

.example-list.cdk-drop-list-dragging .example-box:not(.cdk-drag-placeholder) {
  transition: transform 250ms cubic-bezier(0, 0, 0.2, 1);
}

.example-custom-placeholder {
  background: #ccc;
  border: dotted 3px #999;
  min-height: 60px;
  transition: transform 250ms cubic-bezier(0, 0, 0.2, 1);
}

Upvotes: 5

Related Questions