Reputation: 111
I have a <div>
element with position: absolute
inside a container with position: relative
. Its left
and top
properties are bound to data X and Y in the component.ts
. My purpose is to move the div inside my container using cdk drag and drop.
On the dragEnded
event I retrive the data I need to update the coordinates X and Y and so begins the problem...
<div
class="character"
[style.left.px]="x"
[style.top.px]="y"
cdkDrag
cdkDragBoundary=".grid-container"
(cdkDragEnded)="dragEnded($event, c)"
></div>
I notice that cdk drag and drop apply a property transform: translate3d(x,y,z)
in order to move my div, starting from its original position. So, if I want my div left and top to be bound to my backend properties I can just calculate new coordinates on dragEnd event, apply them, and reset the transform property made by cdk. Everything works.
But the next time I drag the element, material don't apply the transform starting from the new absolute position of my div, but from the original one.
I thought one solution could be to check if the CdkDragEnd event
contains the data relative to the transform starting point and reset it, but I didn't find anything.
Any idea if this proprty is hidden somewhere in the CdkDragEvent? Or have any other solution to this problem?
Upvotes: 10
Views: 9714
Reputation: 8491
Even if the version of @bakunet is working, this is considering bad practice to access private method and may not work, depend on your compiler.
Here on the official angular website, you can find the following solution.
ckdDragFreeDragPosition
<p>
<button (click)="resetPosition()">reset position</button>
</p>
<div class="character" cdkDrag [cdkDragFreeDragPosition]="dragPosition">
Drag me around
</div>
import {Component} from '@angular/core';
/**
* @title Programmatically setting the free drag position
*/
@Component({
selector: 'cdk-drag-drop-free-drag-position-example',
templateUrl: 'cdk-drag-drop-free-drag-position-example.html',
styleUrls: ['cdk-drag-drop-free-drag-position-example.css'],
})
export class CdkDragDropFreeDragPositionExample {
dragPosition = {x: 0, y: 0};
resetPosition() {
this.dragPosition = {x: 0, y: 0};
}
}
ckdDragFreeDragPosition
use :
By default, standalone cdkDrag elements move from their normal DOM position only when manually moved by a user. The element's position can be explicitly set, however, via the cdkDragFreeDragPosition input. Applications commonly use this, for example, to restore a draggable's position after a user has navigated away and then returned.
Upvotes: 4
Reputation: 631
In method that takes CdkDragEnd
event you can reset transform property with event.source._dragRef.reset();
. Example:
public dragEnded(event: CdkDragEnd): void {
if (this.dragEnd.type === "cell" && this.dragStart.type !== "cell") {
this.moveFromList1To2(event.source.element.nativeElement.id);
event.source._dragRef.reset();
}
}
Upvotes: 13
Reputation: 596
I too faced this issue a while back. After a lot of time surfing on the internet for a way to reset the transform
property, I got nothing.
Seems you cannot reset the transform
property. What ever you do, the final position of the drag-div will be calculated by summing up the latest top
, left
, and transform
properties.
My solution was not to change the left
and top
properties of the element dynamically and keep track of the x
and y
values by the (cdkDragEnded)
event emitter
What I did is was,
xInitial = x
and yInitial = y
to store the initial co-ordinates of the div
to dragRender you div
initially with these initial co-ordninates;
<div
class="character"
[style.left.px]="xInitial"
[style.top.px]="yInitial"
cdkDrag
cdkDragBoundary=".grid-container"
(cdkDragEnded)="dragEnded($event, c)"
></div>
Modify dragEnded($event, c)
to keep track of the actual position of the dragged div
dragEnded(event, c) {
let element = event.source.getRootElement();
let newPos = element.getBoundingClientRect();
this.x = newPos.x;
this.y = newPos.y;
}
this.x
and this.y
for initialising the component the next time.Upvotes: 1