Skip to content

Commit 1f34b94

Browse files
authored
fix(cdk/drag-drop): make item and list easier to tree shake (#32604)
Currently we have the `DragDrop` service that creates the `DragRef` and `DropListRef` which contain most of the implementation for the directives. The problem is that by going through the service, we can't tree shake the list if the app is only using the item. These changes move the creation into separate functions.
1 parent 2c4f4bf commit 1f34b94

7 files changed

Lines changed: 90 additions & 46 deletions

File tree

goldens/cdk/drag-drop/index.api.md

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ import { ElementRef } from '@angular/core';
99
import { EventEmitter } from '@angular/core';
1010
import * as i0 from '@angular/core';
1111
import { InjectionToken } from '@angular/core';
12+
import { Injector } from '@angular/core';
1213
import { NgZone } from '@angular/core';
1314
import { Observable } from 'rxjs';
1415
import { OnChanges } from '@angular/core';
@@ -298,16 +299,24 @@ export class CdkDropListGroup<T> implements OnDestroy {
298299
// @public
299300
export function copyArrayItem<T = any>(currentArray: T[], targetArray: T[], currentIndex: number, targetIndex: number): void;
300301

302+
// @public
303+
export function createDragRef<T = unknown>(injector: Injector, element: ElementRef<HTMLElement> | HTMLElement, config?: DragRefConfig): DragRef<T>;
304+
305+
// @public
306+
export function createDropListRef<T = unknown>(injector: Injector, element: ElementRef<HTMLElement> | HTMLElement): DropListRef<T>;
307+
301308
// @public
302309
export type DragAxis = 'x' | 'y';
303310

304311
// @public
305312
export type DragConstrainPosition = (userPointerPosition: Point, dragRef: DragRef, dimensions: DOMRect, pickupPositionInElement: Point) => Point;
306313

307-
// @public
314+
// @public @deprecated
308315
export class DragDrop {
309316
constructor(...args: unknown[]);
317+
// @deprecated
310318
createDrag<T = any>(element: ElementRef<HTMLElement> | HTMLElement, config?: DragRefConfig): DragRef<T>;
319+
// @deprecated
311320
createDropList<T = any>(element: ElementRef<HTMLElement> | HTMLElement): DropListRef<T>;
312321
// (undocumented)
313322
static ɵfac: i0.ɵɵFactoryDeclaration<DragDrop, never>;

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

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -43,9 +43,8 @@ import {CDK_DRAG_HANDLE, CdkDragHandle} from './drag-handle';
4343
import {CdkDragPlaceholder} from './drag-placeholder';
4444
import {CdkDragPreview} from './drag-preview';
4545
import {CDK_DRAG_PARENT} from '../drag-parent';
46-
import {DragRef, Point, PreviewContainer, DragConstrainPosition} from '../drag-ref';
46+
import {DragRef, Point, PreviewContainer, DragConstrainPosition, createDragRef} from '../drag-ref';
4747
import type {CdkDropList} from './drop-list';
48-
import {DragDrop} from '../drag-drop';
4948
import {CDK_DRAG_CONFIG, DragDropConfig, DragStartDelay, DragAxis} from './config';
5049
import {assertElementNode} from './assertions';
5150
import {DragDropRegistry} from '../drag-drop-registry';
@@ -222,9 +221,8 @@ export class CdkDrag<T = any> implements AfterViewInit, OnChanges, OnDestroy {
222221
constructor() {
223222
const dropContainer = this.dropContainer;
224223
const config = inject<DragDropConfig>(CDK_DRAG_CONFIG, {optional: true});
225-
const dragDrop = inject(DragDrop);
226224

227-
this._dragRef = dragDrop.createDrag(this.element, {
225+
this._dragRef = createDragRef(this._injector, this.element, {
228226
dragStartThreshold:
229227
config && config.dragStartThreshold != null ? config.dragStartThreshold : 5,
230228
pointerDirectionChangeThreshold:

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

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -17,16 +17,16 @@ import {
1717
ChangeDetectorRef,
1818
booleanAttribute,
1919
inject,
20+
Injector,
2021
} from '@angular/core';
2122
import {Directionality} from '../../bidi';
2223
import {_IdGenerator} from '../../a11y';
2324
import {ScrollDispatcher} from '../../scrolling';
2425
import {CDK_DROP_LIST, CdkDrag} from './drag';
2526
import {CdkDragDrop, CdkDragEnter, CdkDragExit, CdkDragSortEvent} from '../drag-events';
2627
import {CDK_DROP_LIST_GROUP, CdkDropListGroup} from './drop-list-group';
27-
import {DropListRef} from '../drop-list-ref';
28+
import {createDropListRef, DropListRef} from '../drop-list-ref';
2829
import {DragRef} from '../drag-ref';
29-
import {DragDrop} from '../drag-drop';
3030
import {DropListOrientation, DragAxis, DragDropConfig, CDK_DRAG_CONFIG} from './config';
3131
import {merge, Subject} from 'rxjs';
3232
import {startWith, takeUntil} from 'rxjs/operators';
@@ -197,14 +197,14 @@ export class CdkDropList<T = any> implements OnDestroy {
197197
constructor(...args: unknown[]);
198198

199199
constructor() {
200-
const dragDrop = inject(DragDrop);
201200
const config = inject<DragDropConfig>(CDK_DRAG_CONFIG, {optional: true});
201+
const injector = inject(Injector);
202202

203203
if (typeof ngDevMode === 'undefined' || ngDevMode) {
204204
assertElementNode(this.element.nativeElement, 'cdkDropList');
205205
}
206206

207-
this._dropListRef = dragDrop.createDropList(this.element);
207+
this._dropListRef = createDropListRef(injector, this.element);
208208
this._dropListRef.data = this;
209209

210210
if (config) {

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

Lines changed: 14 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -6,29 +6,19 @@
66
* found in the LICENSE file at https://angular.dev/license
77
*/
88

9-
import {Injectable, NgZone, ElementRef, inject, RendererFactory2, DOCUMENT} from '@angular/core';
10-
11-
import {ViewportRuler} from '../scrolling';
12-
import {DragRef, DragRefConfig} from './drag-ref';
13-
import {DropListRef} from './drop-list-ref';
14-
import {DragDropRegistry} from './drag-drop-registry';
15-
16-
/** Default configuration to be used when creating a `DragRef`. */
17-
const DEFAULT_CONFIG = {
18-
dragStartThreshold: 5,
19-
pointerDirectionChangeThreshold: 5,
20-
};
9+
import {Injectable, ElementRef, inject, Injector} from '@angular/core';
10+
import {createDragRef, DragRef, DragRefConfig} from './drag-ref';
11+
import {createDropListRef, DropListRef} from './drop-list-ref';
2112

2213
/**
2314
* Service that allows for drag-and-drop functionality to be attached to DOM elements.
15+
* @deprecated Use the `createDragRef` or `createDropListRef` function for better tree shaking.
16+
* Will be removed in v23.
17+
* @breaking-change 23.0.0
2418
*/
2519
@Injectable({providedIn: 'root'})
2620
export class DragDrop {
27-
private _document = inject(DOCUMENT);
28-
private _ngZone = inject(NgZone);
29-
private _viewportRuler = inject(ViewportRuler);
30-
private _dragDropRegistry = inject(DragDropRegistry);
31-
private _renderer = inject(RendererFactory2).createRenderer(null, null);
21+
private _injector = inject(Injector);
3222

3323
constructor(...args: unknown[]);
3424
constructor() {}
@@ -37,33 +27,23 @@ export class DragDrop {
3727
* Turns an element into a draggable item.
3828
* @param element Element to which to attach the dragging functionality.
3929
* @param config Object used to configure the dragging behavior.
30+
* @deprecated Use the `createDragRef` function that provides better tree shaking.
31+
* @breaking-change 23.0.0
4032
*/
4133
createDrag<T = any>(
4234
element: ElementRef<HTMLElement> | HTMLElement,
43-
config: DragRefConfig = DEFAULT_CONFIG,
35+
config?: DragRefConfig,
4436
): DragRef<T> {
45-
return new DragRef<T>(
46-
element,
47-
config,
48-
this._document,
49-
this._ngZone,
50-
this._viewportRuler,
51-
this._dragDropRegistry,
52-
this._renderer,
53-
);
37+
return createDragRef(this._injector, element, config);
5438
}
5539

5640
/**
5741
* Turns an element into a drop list.
5842
* @param element Element to which to attach the drop list functionality.
43+
* @deprecated Use the `createDropListRef` function that provides better tree shaking.
44+
* @breaking-change 23.0.0
5945
*/
6046
createDropList<T = any>(element: ElementRef<HTMLElement> | HTMLElement): DropListRef<T> {
61-
return new DropListRef<T>(
62-
element,
63-
this._dragDropRegistry,
64-
this._document,
65-
this._ngZone,
66-
this._viewportRuler,
67-
);
47+
return createDropListRef(this._injector, element);
6848
}
6949
}

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

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,10 +12,13 @@ import {coerceElement} from '../coercion';
1212
import {_getEventTarget, _getShadowRoot} from '../platform';
1313
import {ViewportRuler} from '../scrolling';
1414
import {
15+
DOCUMENT,
1516
ElementRef,
1617
EmbeddedViewRef,
18+
Injector,
1719
NgZone,
1820
Renderer2,
21+
RendererFactory2,
1922
TemplateRef,
2023
ViewContainerRef,
2124
signal,
@@ -124,6 +127,35 @@ const dragImportantProperties = new Set([
124127
*/
125128
export type PreviewContainer = 'global' | 'parent' | ElementRef<HTMLElement> | HTMLElement;
126129

130+
/**
131+
* Creates a `DragRef` for an element, turning it into a draggable item.
132+
* @param injector Injector used to resolve dependencies.
133+
* @param element Element to which to attach the dragging functionality.
134+
* @param config Object used to configure the dragging behavior.
135+
*/
136+
export function createDragRef<T = unknown>(
137+
injector: Injector,
138+
element: ElementRef<HTMLElement> | HTMLElement,
139+
config: DragRefConfig = {
140+
dragStartThreshold: 5,
141+
pointerDirectionChangeThreshold: 5,
142+
},
143+
): DragRef<T> {
144+
const renderer =
145+
injector.get(Renderer2, null, {optional: true}) ||
146+
injector.get(RendererFactory2).createRenderer(null, null);
147+
148+
return new DragRef(
149+
element,
150+
config,
151+
injector.get(DOCUMENT),
152+
injector.get(NgZone),
153+
injector.get(ViewportRuler),
154+
injector.get(DragDropRegistry),
155+
renderer,
156+
);
157+
}
158+
127159
/**
128160
* Reference to a draggable item. Used to manipulate or dispose of the item.
129161
*/

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

Lines changed: 19 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@
66
* found in the LICENSE file at https://angular.dev/license
77
*/
88

9-
import {ElementRef, NgZone} from '@angular/core';
9+
import {DOCUMENT, ElementRef, Injector, NgZone} from '@angular/core';
1010
import {Direction} from '../bidi';
1111
import {coerceElement} from '../coercion';
1212
import {ViewportRuler} from '../scrolling';
@@ -49,6 +49,24 @@ enum AutoScrollHorizontalDirection {
4949
RIGHT,
5050
}
5151

52+
/**
53+
* Creates a `DropListRef` for an element, turning it into a drop list.
54+
* @param injector Injector used to resolve dependencies.
55+
* @param element Element to which to attach the drop list functionality.
56+
*/
57+
export function createDropListRef<T = unknown>(
58+
injector: Injector,
59+
element: ElementRef<HTMLElement> | HTMLElement,
60+
): DropListRef<T> {
61+
return new DropListRef(
62+
element,
63+
injector.get(DragDropRegistry),
64+
injector.get(DOCUMENT),
65+
injector.get(NgZone),
66+
injector.get(ViewportRuler),
67+
);
68+
}
69+
5270
/**
5371
* Reference to a drop list. Used to manipulate or dispose of the container.
5472
*/

src/cdk/drag-drop/public-api.ts

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -7,8 +7,15 @@
77
*/
88

99
export {DragDrop} from './drag-drop';
10-
export {DragRef, DragRefConfig, Point, PreviewContainer, DragConstrainPosition} from './drag-ref';
11-
export {DropListRef} from './drop-list-ref';
10+
export {
11+
DragRef,
12+
DragRefConfig,
13+
Point,
14+
PreviewContainer,
15+
DragConstrainPosition,
16+
createDragRef,
17+
} from './drag-ref';
18+
export {DropListRef, createDropListRef} from './drop-list-ref';
1219
export {CDK_DRAG_PARENT} from './drag-parent';
1320

1421
export * from './drag-events';

0 commit comments

Comments
 (0)