I am creating a web app using Angular and Material, I want to be able to drag, drop and resize my sections. Is there a way it can be done using Angular Material drag and drop CDK?
If you are looking for a "non-third-party dependent" solution, then the following is the best.
The following has been tested against Angular 9.
The original example
The folked version (same as above, in case if the original gets deleted)
HTML
<div #resizeBox class="container" style="position: relative;" [style.width.px]="width"
[style.height.px]="height">
<span #dragHandleCorner [cdkDragLockAxis]="lockAxis" class="dragHandle corner" cdkDrag (cdkDragMoved)="dragMove(dragHandleCorner, $event)"></span>
<span #dragHandleRight cdkDragLockAxis="x" class="dragHandle right" cdkDrag (cdkDragMoved)="dragMove(dragHandleRight, $event)"></span>
<span #dragHandleBottom cdkDragLockAxis="y" class="dragHandle bottom" cdkDrag (cdkDragMoved)="dragMove(dragHandleBottom, $event)"></span>
<span class="full" style="width: 100%;">Hello World!</span>
</div>
Component.ts
import { CdkDragMove } from '@angular/cdk/drag-drop';
import { AfterViewInit, Component, ElementRef, NgZone, ViewChild } from '@angular/core';
@Component({
selector: 'my-app',
templateUrl: './app.component.html',
styleUrls: [ './app.component.css' ]
})
export class AppComponent implements AfterViewInit {
@ViewChild('resizeBox') resizeBox: ElementRef;
@ViewChild('dragHandleCorner') dragHandleCorner: ElementRef;
@ViewChild('dragHandleRight') dragHandleRight: ElementRef;
@ViewChild('dragHandleBottom') dragHandleBottom: ElementRef;
get resizeBoxElement(): HTMLElement {
return this.resizeBox.nativeElement;
}
get dragHandleCornerElement(): HTMLElement {
return this.dragHandleCorner.nativeElement;
}
get dragHandleRightElement(): HTMLElement {
return this.dragHandleRight.nativeElement;
}
get dragHandleBottomElement(): HTMLElement {
return this.dragHandleBottom.nativeElement;
}
constructor(private ngZone: NgZone) {}
ngAfterViewInit() {
this.setAllHandleTransform();
}
setAllHandleTransform() {
const rect = this.resizeBoxElement.getBoundingClientRect();
this.setHandleTransform(this.dragHandleCornerElement, rect, 'both');
this.setHandleTransform(this.dragHandleRightElement, rect, 'x');
this.setHandleTransform(this.dragHandleBottomElement, rect, 'y');
}
setHandleTransform(
dragHandle: HTMLElement,
targetRect: ClientRect | DOMRect,
position: 'x' | 'y' | 'both'
) {
const dragRect = dragHandle.getBoundingClientRect();
const translateX = targetRect.width - dragRect.width;
const translateY = targetRect.height - dragRect.height;
if (position === 'x') {
dragHandle.style.transform = `translate3d(${translateX}px, 0, 0)`;
}
if (position === 'y') {
dragHandle.style.transform = `translate3d(0, ${translateY}px, 0)`;
}
if (position === 'both') {
dragHandle.style.transform = `translate3d(${translateX}px, ${translateY}px, 0)`;
}
}
dragMove(dragHandle: HTMLElement, $event: CdkDragMove<any>) {
this.ngZone.runOutsideAngular(() => {
this.resize(dragHandle, this.resizeBoxElement);
});
}
resize(dragHandle: HTMLElement, target: HTMLElement) {
const dragRect = dragHandle.getBoundingClientRect();
const targetRect = target.getBoundingClientRect();
const width = dragRect.left - targetRect.left + dragRect.width;
const height = dragRect.top - targetRect.top + dragRect.height;
target.style.width = width + 'px';
target.style.height = height + 'px';
this.setAllHandleTransform();
}
}
CSS
.container {
position: relative;
background-color: gray;
}
.full {
width: 100%;
background: yellow;
}
.dragHandle {
position: absolute;
background-color: red;
}
.dragHandle.corner {
width: 15px;
height: 15px;
cursor: nwse-resize;
}
.dragHandle.right {
width: 2px;
height: 100%;
cursor: ew-resize;
}
.dragHandle.bottom {
height: 2px;
width: 100%;
cursor: ns-resize;
}
Hope this helps some one :)
Thanks.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With