Search code examples
angularangular-materialdrag-and-dropangular-cdk-drag-drop

Angular: Drag and Drop - Fill [cdkDropListConnectedTo] dynamically


Drag and drop should be possible as follows.

  • You can move items from container 1 to containers 2, 3 or 4.
  • You are not allowed to move items from container 2, 3 or 4 to container 1.
  • items from containers 2 to 4 can be moved back and forth.

enter image description here

I'm just missing [cdkDropListConnectedTo]

How do i have to populate [cdkDropListConnectedTo] to meet my needs?

Redundant code should be avoided as much as possible.

This is my current code.

<div *ngFor="let book of this.books; let i = index">
    <div>
        <div
            cdkDropList
            id="book-container-{{i}}"
            #ref{{i}}="cdkDropList"
            [cdkDropListData]="book.getDropListData()"
            [cdkDropListConnectedTo]= "[]"
            (cdkDropListDropped)="drop($event)">
            <div>
                <p class="headline">{{book.getHeadline()}}</p>
            </div>
        </div>
    </div>
</div>


Solution

  • Here is a example. You can move from container one to container two. But not back from two to one.

    Here is the solution for the html part:

    Use the cdkDropListEnterPredicateattribute. This fires if any item over the other container. Here is the documentation.

    <div
      cdkDropList
      id="two"
      [cdkDropListData]="basket"
      class="example-list"
      (cdkDropListDropped)="drop($event)"
      [cdkDropListEnterPredicate]="canDrop">
          <div class="example-box" *ngFor="let item of basket" cdkDrag>{{item}}</div>
    </div>
    

    The code behind:

    Here we check the id of the item.dropContainer (the start container it was nested) and the list.id (the target container you wanna drop). Simple if you move from two -> one return false.

      canDrop(item: CdkDrag, list: CdkDropList) {
        console.log(item.dropContainer.id, list.id);
    
        if (item.dropContainer.id === 'two' && list.id === 'one') return false;
        return true;
      }
    

    Try it all here in Stackblitz!