Skip to content

Commit fd70c07

Browse files
crisbetojosephperrott
authored andcommitted
fix(drag-drop): remove circular dependencies (#12554)
1 parent 7d0e69b commit fd70c07

File tree

5 files changed

+70
-74
lines changed

5 files changed

+70
-74
lines changed

src/cdk-experimental/drag-drop/drag-drop-registry.spec.ts

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -6,15 +6,15 @@ import {
66
createTouchEvent,
77
dispatchTouchEvent,
88
} from '@angular/cdk/testing';
9-
import {CdkDragDropRegistry} from './drag-drop-registry';
9+
import {DragDropRegistry} from './drag-drop-registry';
1010
import {DragDropModule} from './drag-drop-module';
1111
import {CdkDrag} from './drag';
1212
import {CdkDrop} from './drop';
1313

1414
describe('DragDropRegistry', () => {
1515
let fixture: ComponentFixture<SimpleDropZone>;
1616
let testComponent: SimpleDropZone;
17-
let registry: CdkDragDropRegistry;
17+
let registry: DragDropRegistry<CdkDrag, CdkDrop>;
1818

1919
beforeEach(fakeAsync(() => {
2020
TestBed.configureTestingModule({
@@ -26,7 +26,7 @@ describe('DragDropRegistry', () => {
2626
testComponent = fixture.componentInstance;
2727
fixture.detectChanges();
2828

29-
inject([CdkDragDropRegistry], (c: CdkDragDropRegistry) => {
29+
inject([DragDropRegistry], (c: DragDropRegistry<CdkDrag, CdkDrop>) => {
3030
registry = c;
3131
})();
3232
}));
@@ -59,7 +59,7 @@ describe('DragDropRegistry', () => {
5959
registry.startDragging(firstItem, createMouseEvent('mousedown'));
6060
expect(registry.isDragging(firstItem)).toBe(true);
6161

62-
registry.remove(firstItem);
62+
registry.removeDragItem(firstItem);
6363
expect(registry.isDragging(firstItem)).toBe(false);
6464
});
6565

@@ -130,7 +130,7 @@ describe('DragDropRegistry', () => {
130130
});
131131

132132
it('should not throw when trying to register the same container again', () => {
133-
expect(() => registry.register(testComponent.dropInstances.first)).not.toThrow();
133+
expect(() => registry.registerDropContainer(testComponent.dropInstances.first)).not.toThrow();
134134
});
135135

136136
it('should throw when trying to register a different container with the same id', () => {

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

Lines changed: 54 additions & 61 deletions
Original file line numberDiff line numberDiff line change
@@ -10,8 +10,6 @@ import {Injectable, NgZone, OnDestroy, Inject} from '@angular/core';
1010
import {DOCUMENT} from '@angular/common';
1111
import {supportsPassiveEventListeners} from '@angular/cdk/platform';
1212
import {Subject} from 'rxjs';
13-
import {CdkDrop} from './drop';
14-
import {CdkDrag} from './drag';
1513

1614
/** Event options that can be used to bind an active event. */
1715
const activeEventOptions = supportsPassiveEventListeners() ? {passive: false} : false;
@@ -20,35 +18,38 @@ const activeEventOptions = supportsPassiveEventListeners() ? {passive: false} :
2018
type PointerEventHandler = (event: TouchEvent | MouseEvent) => void;
2119

2220
/**
23-
* Service that keeps track of all the `CdkDrag` and `CdkDrop` instances, and
24-
* manages global event listeners on the `document`.
21+
* Service that keeps track of all the drag item and drop container
22+
* instances, and manages global event listeners on the `document`.
2523
* @docs-private
2624
*/
25+
// Note: this class is generic, rather than referencing CdkDrag and CdkDrop directly, in order to
26+
// avoid circular imports. If we were to reference them here, importing the registry into the
27+
// classes that are registering themselves will introduce a circular import.
2728
@Injectable({providedIn: 'root'})
28-
export class CdkDragDropRegistry implements OnDestroy {
29+
export class DragDropRegistry<I, C extends {id: string}> implements OnDestroy {
2930
private _document: Document;
3031

31-
/** Registered `CdkDrop` instances. */
32-
private _dropInstances = new Set<CdkDrop>();
32+
/** Registered drop container instances. */
33+
private _dropInstances = new Set<C>();
3334

34-
/** Registered `CdkDrag` instances. */
35-
private _dragInstances = new Set<CdkDrag>();
35+
/** Registered drag item instances. */
36+
private _dragInstances = new Set<I>();
3637

37-
/** `CdkDrag` instances that are currently being dragged. */
38-
private _activeDragInstances = new Set<CdkDrag>();
38+
/** Drag item instances that are currently being dragged. */
39+
private _activeDragInstances = new Set<I>();
3940

4041
/** Keeps track of the event listeners that we've bound to the `document`. */
4142
private _globalListeners = new Map<string, {handler: PointerEventHandler, options?: any}>();
4243

4344
/**
4445
* Emits the `touchmove` or `mousemove` events that are dispatched
45-
* while the user is dragging a `CdkDrag` instance.
46+
* while the user is dragging a drag item instance.
4647
*/
4748
readonly pointerMove: Subject<TouchEvent | MouseEvent> = new Subject<TouchEvent | MouseEvent>();
4849

4950
/**
5051
* Emits the `touchend` or `mouseup` events that are dispatched
51-
* while the user is dragging a `CdkDrag` instance.
52+
* while the user is dragging a drag item instance.
5253
*/
5354
readonly pointerUp: Subject<TouchEvent | MouseEvent> = new Subject<TouchEvent | MouseEvent>();
5455

@@ -58,52 +59,44 @@ export class CdkDragDropRegistry implements OnDestroy {
5859
this._document = _document;
5960
}
6061

61-
/** Adds a `CdkDrop` instance to the registry. */
62-
register(drop: CdkDrop);
63-
64-
/** Adds a `CdkDrag` instance to the registry. */
65-
register(drag: CdkDrag);
66-
67-
register(instance: CdkDrop | CdkDrag) {
68-
if (instance instanceof CdkDrop) {
69-
if (!this._dropInstances.has(instance)) {
70-
if (this.getDropContainer(instance.id)) {
71-
throw Error(`Drop instance with id "${instance.id}" has already been registered.`);
72-
}
73-
74-
this._dropInstances.add(instance);
75-
}
76-
} else {
77-
this._dragInstances.add(instance);
78-
79-
if (this._dragInstances.size === 1) {
80-
this._ngZone.runOutsideAngular(() => {
81-
// The event handler has to be explicitly active, because
82-
// newer browsers make it passive by default.
83-
this._document.addEventListener('touchmove', this._preventScrollListener,
84-
activeEventOptions);
85-
});
62+
/** Adds a drop container to the registry. */
63+
registerDropContainer(drop: C) {
64+
if (!this._dropInstances.has(drop)) {
65+
if (this.getDropContainer(drop.id)) {
66+
throw Error(`Drop instance with id "${drop.id}" has already been registered.`);
8667
}
68+
69+
this._dropInstances.add(drop);
8770
}
8871
}
8972

90-
/** Removes a `CdkDrop` instance from the registry. */
91-
remove(drop: CdkDrop);
73+
/** Adds a drag item instance to the registry. */
74+
registerDragItem(drag: I) {
75+
this._dragInstances.add(drag);
76+
77+
if (this._dragInstances.size === 1) {
78+
this._ngZone.runOutsideAngular(() => {
79+
// The event handler has to be explicitly active, because
80+
// newer browsers make it passive by default.
81+
this._document.addEventListener('touchmove', this._preventScrollListener,
82+
activeEventOptions);
83+
});
84+
}
85+
}
9286

93-
/** Removes a `CdkDrag` instance from the registry. */
94-
remove(drag: CdkDrag);
87+
/** Removes a drop container from the registry. */
88+
removeDropContainer(drop: C) {
89+
this._dropInstances.delete(drop);
90+
}
9591

96-
remove(instance: CdkDrop | CdkDrag) {
97-
if (instance instanceof CdkDrop) {
98-
this._dropInstances.delete(instance);
99-
} else {
100-
this._dragInstances.delete(instance);
101-
this.stopDragging(instance);
92+
/** Removes a drag item instance from the registry. */
93+
removeDragItem(drag: I) {
94+
this._dragInstances.delete(drag);
95+
this.stopDragging(drag);
10296

103-
if (this._dragInstances.size === 0) {
104-
this._document.removeEventListener('touchmove', this._preventScrollListener,
105-
activeEventOptions as any);
106-
}
97+
if (this._dragInstances.size === 0) {
98+
this._document.removeEventListener('touchmove', this._preventScrollListener,
99+
activeEventOptions as any);
107100
}
108101
}
109102

@@ -112,7 +105,7 @@ export class CdkDragDropRegistry implements OnDestroy {
112105
* @param drag Drag instance which is being dragged.
113106
* @param event Event that initiated the dragging.
114107
*/
115-
startDragging(drag: CdkDrag, event: TouchEvent | MouseEvent) {
108+
startDragging(drag: I, event: TouchEvent | MouseEvent) {
116109
this._activeDragInstances.add(drag);
117110

118111
if (this._activeDragInstances.size === 1) {
@@ -134,28 +127,28 @@ export class CdkDragDropRegistry implements OnDestroy {
134127
}
135128
}
136129

137-
/** Stops dragging a `CdkDrag` instance. */
138-
stopDragging(drag: CdkDrag) {
130+
/** Stops dragging a drag item instance. */
131+
stopDragging(drag: I) {
139132
this._activeDragInstances.delete(drag);
140133

141134
if (this._activeDragInstances.size === 0) {
142135
this._clearGlobalListeners();
143136
}
144137
}
145138

146-
/** Gets whether a `CdkDrag` instance is currently being dragged. */
147-
isDragging(drag: CdkDrag) {
139+
/** Gets whether a drag item instance is currently being dragged. */
140+
isDragging(drag: I) {
148141
return this._activeDragInstances.has(drag);
149142
}
150143

151-
/** Gets a `CdkDrop` instance by its id. */
152-
getDropContainer<T = any>(id: string): CdkDrop<T> | undefined {
144+
/** Gets a drop container by its id. */
145+
getDropContainer(id: string): C | undefined {
153146
return Array.from(this._dropInstances).find(instance => instance.id === id);
154147
}
155148

156149
ngOnDestroy() {
157-
this._dragInstances.forEach(instance => this.remove(instance));
158-
this._dropInstances.forEach(instance => this.remove(instance));
150+
this._dragInstances.forEach(instance => this.removeDragItem(instance));
151+
this._dropInstances.forEach(instance => this.removeDropContainer(instance));
159152
this._clearGlobalListeners();
160153
this.pointerMove.complete();
161154
this.pointerUp.complete();

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

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,7 @@ import {CdkDragStart, CdkDragEnd, CdkDragExit, CdkDragEnter, CdkDragDrop} from '
3131
import {CdkDragPreview} from './drag-preview';
3232
import {CdkDragPlaceholder} from './drag-placeholder';
3333
import {ViewportRuler} from '@angular/cdk/overlay';
34-
import {CdkDragDropRegistry} from './drag-drop-registry';
34+
import {DragDropRegistry} from './drag-drop-registry';
3535
import {Subject, merge} from 'rxjs';
3636
import {takeUntil} from 'rxjs/operators';
3737

@@ -138,10 +138,10 @@ export class CdkDrag<T = any> implements OnDestroy {
138138
private _ngZone: NgZone,
139139
private _viewContainerRef: ViewContainerRef,
140140
private _viewportRuler: ViewportRuler,
141-
private _dragDropRegistry: CdkDragDropRegistry,
141+
private _dragDropRegistry: DragDropRegistry<CdkDrag<T>, CdkDropContainer>,
142142
@Optional() private _dir: Directionality) {
143143
this._document = document;
144-
_dragDropRegistry.register(this);
144+
_dragDropRegistry.registerDragItem(this);
145145
}
146146

147147
/**
@@ -165,7 +165,7 @@ export class CdkDrag<T = any> implements OnDestroy {
165165
}
166166

167167
this._nextSibling = null;
168-
this._dragDropRegistry.remove(this);
168+
this._dragDropRegistry.removeDragItem(this);
169169
this._destroyed.next();
170170
this._destroyed.complete();
171171
}

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

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,9 @@ export interface CdkDropContainer<T = any> {
1313
/** Arbitrary data to attach to all events emitted by this container. */
1414
data: T;
1515

16+
/** Unique ID for the drop zone. */
17+
id: string;
18+
1619
/** Direction in which the list is oriented. */
1720
orientation: 'horizontal' | 'vertical';
1821

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

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,7 @@ import {
2323
import {CdkDrag} from './drag';
2424
import {CdkDragExit, CdkDragEnter, CdkDragDrop} from './drag-events';
2525
import {CDK_DROP_CONTAINER} from './drop-container';
26-
import {CdkDragDropRegistry} from './drag-drop-registry';
26+
import {DragDropRegistry} from './drag-drop-registry';
2727

2828
/** Counter used to generate unique ids for drop zones. */
2929
let _uniqueIdCounter = 0;
@@ -85,14 +85,14 @@ export class CdkDrop<T = any> implements OnInit, OnDestroy {
8585

8686
constructor(
8787
public element: ElementRef<HTMLElement>,
88-
private _dragDropRegistry: CdkDragDropRegistry) {}
88+
private _dragDropRegistry: DragDropRegistry<CdkDrag, CdkDrop<T>>) {}
8989

9090
ngOnInit() {
91-
this._dragDropRegistry.register(this);
91+
this._dragDropRegistry.registerDropContainer(this);
9292
}
9393

9494
ngOnDestroy() {
95-
this._dragDropRegistry.remove(this);
95+
this._dragDropRegistry.removeDropContainer(this);
9696
}
9797

9898
/** Whether an item in the container is being dragged. */

0 commit comments

Comments
 (0)