Skip to content

Commit

Permalink
fix(cdk/drag-drop): constrainPosition now working well with boundary
Browse files Browse the repository at this point in the history
  • Loading branch information
mj3052 committed Aug 31, 2023
1 parent 4095ab7 commit 487d2f2
Show file tree
Hide file tree
Showing 5 changed files with 104 additions and 10 deletions.
23 changes: 23 additions & 0 deletions src/cdk/drag-drop/directives/drag.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -946,6 +946,29 @@ describe('CdkDrag', () => {
expect(dragElement.style.transform).toBe('translate3d(100px, 100px, 0px)');
}));

it('should allow for dragging to be constrained to an element while using constrainPosition', fakeAsync(() => {
const fixture = createComponent(StandaloneDraggable);
fixture.componentInstance.boundary = '.wrapper';
fixture.detectChanges();

fixture.componentInstance.dragInstance.constrainPosition = (
{x, y}: Point,
_dragRef: DragRef,
_dimensions: ClientRect,
pickup: Point,
) => {
x -= pickup.x;
y -= pickup.y;
return {x, y};
};

const dragElement = fixture.componentInstance.dragElement.nativeElement;

expect(dragElement.style.transform).toBeFalsy();
dragElementViaMouse(fixture, dragElement, 300, 300);
expect(dragElement.style.transform).toBe('translate3d(100px, 100px, 0px)');
}));

it('should be able to pass in a DOM node as the boundary', fakeAsync(() => {
const fixture = createComponent(StandaloneDraggable);
fixture.componentInstance.boundary = fixture.nativeElement.querySelector('.wrapper');
Expand Down
15 changes: 12 additions & 3 deletions src/cdk/drag-drop/drag-ref.ts
Original file line number Diff line number Diff line change
Expand Up @@ -1238,13 +1238,22 @@ export class DragRef<T = any> {
: point;

if (this.lockAxis === 'x' || dropContainerLock === 'x') {
y = this._pickupPositionOnPage.y;
y =
this._pickupPositionOnPage.y -
(this.constrainPosition ? this._pickupPositionInElement.y : 0);
} else if (this.lockAxis === 'y' || dropContainerLock === 'y') {
x = this._pickupPositionOnPage.x;
x =
this._pickupPositionOnPage.x -
(this.constrainPosition ? this._pickupPositionInElement.x : 0);
}

if (this._boundaryRect) {
const {x: pickupX, y: pickupY} = this._pickupPositionInElement;
// If not using a custom constrain we need to account for the pickup position in the element
// otherwise we do not need to do this, as it has already been accounted for
const {x: pickupX, y: pickupY} = !this.constrainPosition
? this._pickupPositionInElement
: {x: 0, y: 0};

const boundaryRect = this._boundaryRect;
const {width: previewWidth, height: previewHeight} = this._getPreviewRect();
const minY = boundaryRect.top + pickupY;
Expand Down
55 changes: 48 additions & 7 deletions src/dev-app/drag-drop/drag-drop-demo.html
Original file line number Diff line number Diff line change
@@ -1,12 +1,12 @@
<div cdkDropListGroup>
<div class="demo-list">

<h2>To do</h2>
<div
cdkDropList
(cdkDropListDropped)="drop($event)"
[cdkDropListLockAxis]="axisLock"
[cdkDropListData]="todo">
[cdkDropListData]="todo"
>
<div *ngFor="let item of todo" cdkDrag>
{{item}}
<mat-icon cdkDragHandle svgIcon="dnd-move"></mat-icon>
Expand All @@ -20,7 +20,8 @@ <h2>Done</h2>
cdkDropList
(cdkDropListDropped)="drop($event)"
[cdkDropListLockAxis]="axisLock"
[cdkDropListData]="done">
[cdkDropListData]="done"
>
<div *ngFor="let item of done" cdkDrag>
{{item}}
<mat-icon cdkDragHandle svgIcon="dnd-move"></mat-icon>
Expand All @@ -37,7 +38,8 @@ <h2>Ages</h2>
cdkDropListOrientation="horizontal"
(cdkDropListDropped)="drop($event)"
[cdkDropListLockAxis]="axisLock"
[cdkDropListData]="ages">
[cdkDropListData]="ages"
>
<div *ngFor="let item of ages" cdkDrag>
{{item}}
<mat-icon cdkDragHandle svgIcon="dnd-move"></mat-icon>
Expand All @@ -52,7 +54,8 @@ <h2>Preferred Ages</h2>
cdkDropListOrientation="horizontal"
(cdkDropListDropped)="drop($event)"
[cdkDropListLockAxis]="axisLock"
[cdkDropListData]="preferredAges">
[cdkDropListData]="preferredAges"
>
<div *ngFor="let item of preferredAges" cdkDrag>
{{item}}
<mat-icon cdkDragHandle svgIcon="dnd-move"></mat-icon>
Expand All @@ -63,7 +66,45 @@ <h2>Preferred Ages</h2>

<div class="demo-list">
<h2>Free dragging</h2>
<div cdkDrag class="demo-free-draggable" [cdkDragLockAxis]="axisLock" [cdkDragStartDelay]="dragStartDelay">Drag me around</div>
<div
cdkDrag
class="demo-free-draggable"
[cdkDragLockAxis]="axisLock"
[cdkDragStartDelay]="dragStartDelay"
>
Drag me around
</div>
</div>

<div>
<h2>Drag with box boundary</h2>
<div class="demo-constrain-box" id="constrain-box-1">
<div
cdkDrag
class="demo-free-draggable"
[cdkDragLockAxis]="axisLock"
[cdkDragStartDelay]="dragStartDelay"
cdkDragBoundary="#constrain-box-1"
>
Drag me around
</div>
</div>
</div>

<div>
<h2>Drag with box boundary and custom constrain</h2>
<div class="demo-constrain-box" id="constrain-box-2">
<div
cdkDrag
class="demo-free-draggable"
[cdkDragLockAxis]="axisLock"
[cdkDragStartDelay]="dragStartDelay"
cdkDragBoundary="#constrain-box-2"
[cdkDragConstrainPosition]="constrainPosition"
>
Drag me around
</div>
</div>
</div>

<div>
Expand All @@ -90,6 +131,6 @@ <h2>Axis locking</h2>
<h2>Drag start delay</h2>

<mat-form-field>
<input matInput placeholder="Drag start delay" value="0" [(ngModel)]="dragStartDelay">
<input matInput placeholder="Drag start delay" value="0" [(ngModel)]="dragStartDelay" />
</mat-form-field>
</div>
6 changes: 6 additions & 0 deletions src/dev-app/drag-drop/drag-drop-demo.scss
Original file line number Diff line number Diff line change
Expand Up @@ -99,3 +99,9 @@ pre {
justify-content: center;
align-items: center;
}

.demo-constrain-box {
width: 600px;
height: 400px;
border: 1px solid black;
}
15 changes: 15 additions & 0 deletions src/dev-app/drag-drop/drag-drop-demo.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,9 @@ import {
DragDropModule,
moveItemInArray,
transferArrayItem,
Point,
DragRef,
CdkDrag,
} from '@angular/cdk/drag-drop';
import {CommonModule} from '@angular/common';
import {FormsModule} from '@angular/forms';
Expand Down Expand Up @@ -74,4 +77,16 @@ export class DragAndDropDemo {
);
}
}

constrainPosition(
{x, y}: Point,
_dragRef: DragRef,
_dimensions: ClientRect,
pickup: Point,
): Point {
// Just returning the original top left corner to not modify position
x -= pickup.x;
y -= pickup.y;
return {x, y};
}
}

0 comments on commit 487d2f2

Please sign in to comment.