I'm trying to get a different animation when releasing a dragged component, based on the drop container.
Basically, I have two cdkDropList. One is a list of cards (multiple draggable elements), the other is a card viewer with only one element, twice the size. The user can drag a card from the list to the viewer, to have a better view.
When the user drag a card, then release it, two cases are possible:
You can animate the card sliding to its destination position with the following css:
.cdk-drag-animating {
transition: transform 300ms cubic-bezier(0, 0, 0.2, 1);
}
So far, so good.
However, I must now add a conditional css rule, adding a "transform: scale(2);" if the drop container is the viewer.
And this is where I'm stuck!
I'm trying to avoid direct DOM access, following the angular guideline, so I want to add a class to the card while its animated. But CDK don't seem to have a way to get a reference of the preview/animating component!
I've managed to get the target size and the dragging component, with the following code in my component ts:
onDragEnter(event: CdkDragEnter) {
if (_.contains(event.container.element.nativeElement.classList,"large")){
this.targetSize= "large";
} else {
this.targetSize= "medium";
}
}
onDragRelease(event: CdkDragRelease) {
this.renderer.addClass(event.source.element.nativeElement, this.targetSize);
}
However, this reference is of the dragging object, and NOT the preview one! When putting a very long timer on the animation to allow me to inspect it, I can see the following DOM elements:
<div _ngcontent-auk-c7="" cdkdrag="" class="cdk-drag large"
ng-reflect-data="[object Object]" style="display: none;">...</div>
<div _ngcontent-auk-c7="" cdkdrag="" class="cdk-drag cdk-drag-preview cdk-drag-animating"
ng-reflect-data="[object Object]" style="touch-action: none; -webkit-user-drag: none; -webkit-tap-highlight-color: transparent; user-select: none; width: 135px; height: 175px; transform: translate3d(415px, 84px, 0px); pointer-events: none; margin: 0px; position: fixed; top: 0px; left: 0px; z-index: 1000;" dir="ltr"><!----><div _ngcontent-auk-c7="" class="card-holder medium"><app-card-base _ngcontent-auk-c7="" _nghost-auk-c8="" ng-reflect-card="[object Object]" ng-reflect-size="medium"><div _ngcontent-auk-c8="" class="card-container medium flip-front" ng-reflect-klass="card-container" ng-reflect-ng-class="medium,flip-front">...</div>
As you can see, we have two elements, one with the correct class "large", but on "display:none", and a second, with the classes "cdk-drag-preview cdk-drag-animating", but not the new class "large".
So, as I cannot add a class to this second element, I cannot make it conditionally change its animation...
A strange side effect is that the new class "large" is added to the card, and future cdk-drag-preview from this card will then have the "large" class! However, it's not good since it seems to indicate I should had my class before the drag start, when I don't know if the user will really drag it to the viewer dropList..
TL;DR :
Ok so it's not really what I wanted, but it works..
In the cdkDragReleased event, I get a reference of the cdkDragPreview element with "document.querySelector"...
I don't think it follow the guidelines of Angular, but at least I made it work, and now my card animation scales correctly based on the target DropList..
onDragRelease(event: CdkDragRelease) {
const preview = new ElementRef<HTMLElement>(document.querySelector(".cdk-drag.cdk-drag-preview"));
this.renderer.addClass(preview.nativeElement, this.targetSize);
}