Search code examples
angulardrag-and-drop

Refresh displayed data between lists when drag and drop happens


I have two lists connected with the CdkDropList Angular event, when I drag an element from one of the lists, the arrays are updated correctly, but in the visualization it is not removed from the list in which the element was dragged and it is duplicated (only visually) the moved item. Also if I drag the same element from the initial list again, it looks like the same element is being dragged, but in reality it is moving the next element (which is now the first element in the initial array) I put a video where this will be seen more clearlyenter image description here

Here is the code. HTML:

<div cdkDropList #actionsList="cdkDropList" [cdkDropListData]="actionsWithoutManagement"
     [cdkDropListConnectedTo]="[managementActionsList]" (cdkDropListDropped)="drop($event)">
  <div *ngFor="let item of filteredOptions" cdkDrag>
     <span>{{item.buttonValueTranslated }}</span>
     <span>{{item.buttonValue}}</span>
  </div>
</div>


<div cdkDropList #managementActionsList="cdkDropList" [cdkDropListData]="managementActions"
     [cdkDropListConnectedTo]="[actionList]" (cdkDropListDropped)="drop($event)">
   <div *ngFor="let item of managementActions" cdkDrag>
      <span>{{ item.buttonValueTranslated }}</span>
      <span>{{ item.buttonValue }}</span>
   </div>
</div>

component.ts:

import { Component, Input, OnDestroy, OnInit } from '@angular/core';
import { FormArray, FormBuilder, FormControl, FormGroup } from '@angular/forms';
import { CdkDragDrop, moveItemInArray,transferArrayItem,} from '@angular/cdk/drag-drop';
import { Observable, Subject, Subscription } from 'rxjs';


@Component({
  selector: 'actions',
  templateUrl: './actions.component.html',
  styleUrls: ['./actions.component.scss'],
})

export class ActionsComponent implements OnInit, OnDestroy
{
...

  drop(event: CdkDragDrop<any[]>, from: string) {
      this.actionsInManagementForm?.clear();
      console.log(this.actionsWithoutManagement)
      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,
        );
  }
}

Anyone knows why is this happening?


Solution

  • Looks like your issue is with using two different lists:

    <!-- Source for the cdkDropList: actionsWithoutManagement-->
    <div 
      cdkDropList 
      #actionsList="cdkDropList"
      [cdkDropListData]="actionsWithoutManagement"
      [cdkDropListConnectedTo]="[managementActionsList]"
      (cdkDropListDropped)="drop($event)"
    >
      <!-- Source for the displayed data: filteredOptions-->
      <div *ngFor="let item of filteredOptions" cdkDrag>
       <!-- ... -->
      </div>
    </div>
    

    If you don't update the filteredOptions array after the successful drag&drop, you'll see the same list, but then the indexes won't match then.

    List: [A, B, C, ...] 
    Filtered: [A, B, C, ...]
    
    //After drag&drop
    List [B, C, ...]
    Filtered: [A, B, C, ...]
    

    That's why you are moving A from the filtered list, but see B being added to managementActionsList.