Skip to content

Commit fb03d76

Browse files
committed
feat(cdk/drag-drop): introduce resetToBoundary
this commit introduces `resetToBoundary` in DragRef which allows user to align DragItem to its boundary on demand if at one point it was at a place where the boundary element used to be and has shrinked causing DragItem to be outside of the boundary box fixes #30325
1 parent 04ae202 commit fb03d76

File tree

3 files changed

+61
-0
lines changed

3 files changed

+61
-0
lines changed

src/cdk/drag-drop/directives/drag.ts

+5
Original file line numberDiff line numberDiff line change
@@ -284,6 +284,11 @@ export class CdkDrag<T = any> implements AfterViewInit, OnChanges, OnDestroy {
284284
this._dragRef.reset();
285285
}
286286

287+
/** Resets drag item to end of boundary element. */
288+
resetToBoundary() {
289+
this._dragRef.resetToBoundary();
290+
}
291+
287292
/**
288293
* Gets the pixel coordinates of the draggable outside of a drop container.
289294
*/

src/cdk/drag-drop/directives/standalone-drag.spec.ts

+43
Original file line numberDiff line numberDiff line change
@@ -46,6 +46,26 @@ describe('Standalone CdkDrag', () => {
4646
expect(dragElement.style.transform).toBe('translate3d(50px, 100px, 0px)');
4747
}));
4848

49+
it('should reset drag item to boundary', fakeAsync(() => {
50+
const fixture = createComponent(DragWithResizeableBoundary);
51+
fixture.detectChanges();
52+
let dragElement = fixture.componentInstance.dragElement.nativeElement;
53+
54+
expect(dragElement.style.transform).toBeFalsy();
55+
dragElementViaMouse(fixture, dragElement, 50, 100);
56+
expect(dragElement.style.transform).toBe('translate3d(50px, 100px, 0px)');
57+
58+
dragElementViaMouse(fixture, dragElement, 300, 300);
59+
expect(dragElement.style.transform).toBe('translate3d(300px, 300px, 0px)');
60+
61+
fixture.componentInstance.resizeBoundary();
62+
fixture.detectChanges();
63+
64+
const position = fixture.componentInstance.dragInstance.getFreeDragPosition();
65+
expect(position).toEqual({x: 100, y: 0});
66+
expect(dragElement.style.transform).toBe('translate3d(100px, 0px, 0px)');
67+
}));
68+
4969
it('should drag an element freely to a particular position when the page is scrolled', fakeAsync(() => {
5070
const fixture = createComponent(StandaloneDraggable);
5171
fixture.detectChanges();
@@ -2047,3 +2067,26 @@ class PlainStandaloneDraggable {
20472067
class StandaloneDraggableWithExternalTemplateHandle {
20482068
@ViewChild('dragElement') dragElement: ElementRef<HTMLElement>;
20492069
}
2070+
2071+
@Component({
2072+
template: `
2073+
<div #boundaryElement class="example-boundary" style="width: 400px; height: 400px">
2074+
<div #dragElement class="example-box" cdkDragBoundary=".example-boundary" cdkDrag style="width: 100px; height: 100px">
2075+
I can only be dragged within the dotted container
2076+
</div>
2077+
</div>
2078+
`,
2079+
imports: [CdkDrag],
2080+
})
2081+
class DragWithResizeableBoundary {
2082+
@ViewChild('boundaryElement') boundaryElement: ElementRef<HTMLElement>;
2083+
2084+
@ViewChild('dragElement') dragElement: ElementRef<HTMLElement>;
2085+
@ViewChild(CdkDrag) dragInstance: CdkDrag;
2086+
2087+
resizeBoundary() {
2088+
this.boundaryElement.nativeElement.style.height = '200px';
2089+
this.boundaryElement.nativeElement.style.width = '200px';
2090+
this.dragInstance.resetToBoundary();
2091+
}
2092+
}

src/cdk/drag-drop/drag-ref.ts

+13
Original file line numberDiff line numberDiff line change
@@ -560,6 +560,19 @@ export class DragRef<T = any> {
560560
this._passiveTransform = {x: 0, y: 0};
561561
}
562562

563+
/** Resets drag item to end of boundary element. */
564+
resetToBoundary(): void {
565+
// can be null if the drag item was never dragged.
566+
if (this._boundaryElement) {
567+
let x = this._boundaryElement.offsetWidth - this._rootElement.offsetWidth,
568+
y = 0; // align it to the top of its boundary
569+
570+
this._rootElement.style.transform = getTransform(x, y);
571+
this._activeTransform = {x, y};
572+
this._passiveTransform = {x, y};
573+
}
574+
}
575+
563576
/**
564577
* Sets a handle as disabled. While a handle is disabled, it'll capture and interrupt dragging.
565578
* @param handle Handle element that should be disabled.

0 commit comments

Comments
 (0)