Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to get the position after drop with cdkDrag?

Hi I need to be able to drag and drop some html elements but I need to know the end position of the drop.

using the cdkDrag directive I see from the docs that there's an event cdkDragEnded.

This is my template:

<div cdkDrop>
  <div cdkDrag (cdkDragEnded)="dragEnd($event)">
    ...other stuff
  </div>
</div>

The callback is:

dragEnd(event: CdkDragEnd) {
  console.log(event);
}

In the console I found what I need but it is a private property of the event event.source._dragRef._passiveTransform and I get the error message when I compile.

Do you know if such data or something else that I can use is exposed somehow?

like image 218
Michele mpp Marostica Avatar asked Jan 30 '19 21:01

Michele mpp Marostica


People also ask

How do you drag and drop CDK?

Start by importing DragDropModule into the NgModule where you want to use drag-and-drop features. You can now add the cdkDrag directive to elements to make them draggable. When outside of a cdkDropList element, draggable elements can be freely moved around the page.

What is cdkDropList?

CdkDropList. Container that wraps a set of draggable items. Selector: [cdkDropList] cdk-drop-list.


2 Answers

Simply use source.getFreeDragPosition() in (getFreeDragPosition) event like this:

dragEnd($event: CdkDragEnd) {
    console.log($event.source.getFreeDragPosition());
}
like image 149
egorgrushin Avatar answered Sep 24 '22 06:09

egorgrushin


The solution I found is to retrieve the style.transform value that cdkDrag set

import { Component, ViewChild, ElementRef } from "@angular/core";
import { CdkDragEnd } from "@angular/cdk/drag-drop";

@Component({
  selector: "item",
  styles: [
    `
      .viewport {
        position: relative;
        background: #ccc;
        display: block;
        margin: auto;
      }
      .item {
        position: absolute;
        background: #aaa;
      }
    `
  ],
  template: `
    <div class="viewport" cdkDrop>
      <div
        #item
        class="item"
        cdkDrag
        (cdkDragEnded)="dragEnd($event)"
        [style.top.px]="initialPosition.y"
        [style.left.px]="initialPosition.x"
      >
        anything
      </div>
    </div>
  `
})
export class CanvasItemComponent {
  constructor() {}

  @ViewChild("item")
  item: ElementRef;

  initialPosition = { x: 100, y: 100 };
  position = { ...this.initialPosition };
  offset = { x: 0, y: 0 };

  dragEnd(event: CdkDragEnd) {
    const transform = this.item.nativeElement.style.transform;
    let regex = /translate3d\(\s?(?<x>[-]?\d*)px,\s?(?<y>[-]?\d*)px,\s?(?<z>[-]?\d*)px\)/;
    var values = regex.exec(transform);
    console.log(transform);
    this.offset = { x: parseInt(values[1]), y: parseInt(values[2]) };

    this.position.x = this.initialPosition.x + this.offset.x;
    this.position.y = this.initialPosition.y + this.offset.y;

    console.log(this.position, this.initialPosition, this.offset);
  }
}

or:

dragEnd(event: CdkDragEnd) {
    this.offset = { ...(<any>event.source._dragRef)._passiveTransform };

    this.position.x = this.initialPosition.x + this.offset.x;
    this.position.y = this.initialPosition.y + this.offset.y;

    console.log(this.position, this.initialPosition, this.offset);
  }

Is there a better way to get that transform x and y values without using private variables?

Edit: The feature will be added in https://github.com/angular/material2/pull/14696

like image 22
Michele mpp Marostica Avatar answered Sep 25 '22 06:09

Michele mpp Marostica