Search code examples
angulardrag-and-dropangular-cdk-drag-drop

How to find on which element value dropped?


I am trying to do simple drag and drop calculation.

user can drag UP and allowed to drop on BH / OT. But issue is couldn't find the ID where user drop, not working onDrop() func.

Suppose if UP(10) value draged and drop on BH(2), desire updated UP and BH value would be 0 and 12 respectively.

StackBlitz link

Tried Code:

<table
  class="hoverable child-table"
  style="background-color: white; border-radius: 8px; width: 100%;"
>
  <tr
    cdkDropList
    cdkDropListSortingDisabled
    cdkDropListLockAxis="x"
    cdkDropListOrientation="horizontal"
    (cdkDropListSorted)="f($event)"
    class="container"
  >
    <th style="background-color: rgb(244, 243, 243); max-width: 5%;">MON</th>

    <td
      style="font-family: 'belgrano', sans-serif; max-width: 5%; border-right: 1px solid black;"
    >
      NULL
    </td>

    <td
      id="BH"
      style="font-family: 'belgrano', sans-serif; max-width: 5%; border-left: 1px solid black;"
      (cdkDropListDropped)="onDrop('BH', $event)"
    >
      {{ BH }}
    </td>

    <td
      id="OT"
      style="font-family: 'belgrano', sans-serif; max-width: 5%;"
      (cdkDropListDropped)="onDrop('OT', $event)"
    >
      {{ OT }}
    </td>

    <td
      id="UP"
      class="draggable"
      style="font-family: 'belgrano', sans-serif; max-width: 5%; border-left: 1px solid black;"
    >
      <span
        cdkDrag
        ocColumnDrag
        (cdkDragMoved)="dragMoved('UP', $event)"
        [cdkDragData]="employee.attendance?.[dateFormt(date)]['UP']"
        class="column"
      >
        {{ UP }}
      </span>
    </td>
  </tr>
</table>

TS:

  BH: number = 2;
  OT: number = 3;
  UP: number = 10;

  draggedTdId: string = '';
  draggedTdValue: any = '';

  dragMoved(tdId: string, e: CdkDragMove) {
    this.draggedTdId = tdId;
    this.draggedTdValue = e.source.data;
    console.log('1', tdId, e.source.data);
  }

  onDrop(tdId: string, event: any) {
    console.log('2', tdId, event);
    const draggedTdId = event.item.element.nativeElement.id;
    const draggedTdValue = event.item.data;

    const droppedTdId = tdId;
    
    console.log('Dragged TD:', draggedTdId, 'Value:', draggedTdValue);
    console.log('Dropped TD:', droppedTdId);
  }

  f(e: any) {
    console.log('sorted', e);
  }

Solution

  • It's not a response, only a brief explanation if how works with cdkDropList.

    We have two directives (a directive makes that a tag becomes a "super tag" (a tag that have methods, properties and we can use events): cdkDragList -we can imagine like a "box"- and cdkDrag -we can imagine like a "ball" that there're inside the "box".

    We can listen events happens to the "box" the cdkDropList: cdkDropListDropped, cdkDropListEntered, cdkDropListExited and cdkDropListSorted

    We can listen events happens to the "balls", the cdkDrag: cdkDragDropped, cdkDragEnded, cdkDragEntered, cdkDragMoved,...

    But only if the tag of .html have the directive (in your code I can not see it)

    In the docs we can capture the arguments of the different events, so, when we have, e.g.

    (cdkDropListDropped)="onDrop($event)"
    

    Our function onDrop will be like

    onDrop(event:CdkDragDrop<T, any>){
       ...
    }
    

    See in the docs that the "Output" are defined like

    @Output('cdkDropListDropped') dropped: EventEmitter<CdkDragDrop<T, any>>

    Well, the argument of the function is of kind CdkDragDrop<T,any> and have the properties (see the "interface" cdkDragDrop): container(the "box" where is dropped the "ball"), currentIndex (in wich index), previousContainer (the box from the "ball" leave), previousIndex (in wich index),...

    Well, nobody talk about list. we can to have an unique box, two box, one box with a unique ball inside...,

    Check your code. Really I don't know if you need three "box" with an unique "ball" in each, or an unique "box" with three "balls", but rememeber you can not use the event (cdkDropListDropped) if your tag is not a cdkDropList