@@ -20,6 +20,8 @@ import {
20
20
EventEmitter ,
21
21
ViewContainerRef ,
22
22
EmbeddedViewRef ,
23
+ ContentChildren ,
24
+ QueryList ,
23
25
} from '@angular/core' ;
24
26
import { CdkDragHandle } from './drag-handle' ;
25
27
import { DOCUMENT } from '@angular/platform-browser' ;
@@ -41,6 +43,8 @@ const activeEventOptions = supportsPassiveEventListeners() ? {passive: false} :
41
43
exportAs : 'cdkDrag' ,
42
44
host : {
43
45
'class' : 'cdk-drag' ,
46
+ '(mousedown)' : '_startDragging($event)' ,
47
+ '(touchstart)' : '_startDragging($event)' ,
44
48
}
45
49
} )
46
50
export class CdkDrag implements AfterContentInit , OnDestroy {
@@ -84,8 +88,8 @@ export class CdkDrag implements AfterContentInit, OnDestroy {
84
88
/** Drop container in which the CdkDrag resided when dragging began. */
85
89
private _initialContainer : CdkDropContainer ;
86
90
87
- /** Element that can be used to drag the draggable item. */
88
- @ContentChild ( CdkDragHandle ) _handle : CdkDragHandle ;
91
+ /** Elements that can be used to drag the draggable item. */
92
+ @ContentChildren ( CdkDragHandle ) _handles : QueryList < CdkDragHandle > ;
89
93
90
94
/** Element that will be used as a template to create the draggable item's preview. */
91
95
@ContentChild ( CdkDragPreview ) _previewTemplate : CdkDragPreview ;
@@ -130,11 +134,6 @@ export class CdkDrag implements AfterContentInit, OnDestroy {
130
134
}
131
135
132
136
ngAfterContentInit ( ) {
133
- // TODO: doesn't handle (pun intended) the handle being destroyed
134
- const dragElement = ( this . _handle ? this . _handle . element : this . element ) . nativeElement ;
135
- dragElement . addEventListener ( 'mousedown' , this . _pointerDown ) ;
136
- dragElement . addEventListener ( 'touchstart' , this . _pointerDown ) ;
137
-
138
137
// Webkit won't preventDefault on a dynamically-added `touchmove` listener, which means that
139
138
// we need to add one ahead of time. See https://bugs.webkit.org/show_bug.cgi?id=184250.
140
139
// TODO: move into a central registry.
@@ -157,8 +156,27 @@ export class CdkDrag implements AfterContentInit, OnDestroy {
157
156
}
158
157
}
159
158
159
+ /** Starts the dragging sequence. */
160
+ _startDragging ( event : MouseEvent | TouchEvent ) {
161
+ // Delegate the event based on whether it started from a handle or the element itself.
162
+ if ( this . _handles . length ) {
163
+ const targetHandle = this . _handles . find ( handle => {
164
+ const element = handle . element . nativeElement ;
165
+ const target = event . target ;
166
+ return ! ! target && ( target === element || element . contains ( target as HTMLElement ) ) ;
167
+ } ) ;
168
+
169
+ if ( targetHandle ) {
170
+ this . _pointerDown ( targetHandle . element , event ) ;
171
+ }
172
+ } else {
173
+ this . _pointerDown ( this . element , event ) ;
174
+ }
175
+ }
176
+
160
177
/** Handler for when the pointer is pressed down on the element or the handle. */
161
- private _pointerDown = ( event : MouseEvent | TouchEvent ) => {
178
+ private _pointerDown = ( referenceElement : ElementRef < HTMLElement > ,
179
+ event : MouseEvent | TouchEvent ) => {
162
180
if ( this . _isDragging ) {
163
181
return ;
164
182
}
@@ -169,7 +187,7 @@ export class CdkDrag implements AfterContentInit, OnDestroy {
169
187
// If we have a custom preview template, the element won't be visible anyway so we avoid the
170
188
// extra `getBoundingClientRect` calls and just move the preview next to the cursor.
171
189
this . _pickupPositionInElement = this . _previewTemplate ? { x : 0 , y : 0 } :
172
- this . _getPointerPositionInElement ( event ) ;
190
+ this . _getPointerPositionInElement ( referenceElement , event ) ;
173
191
this . _pickupPositionOnPage = this . _getPointerPositionOnPage ( event ) ;
174
192
this . _registerMoveListeners ( event ) ;
175
193
@@ -365,11 +383,13 @@ export class CdkDrag implements AfterContentInit, OnDestroy {
365
383
366
384
/**
367
385
* Figures out the coordinates at which an element was picked up.
386
+ * @param referenceElement Element that initiated the dragging.
368
387
* @param event Event that initiated the dragging.
369
388
*/
370
- private _getPointerPositionInElement ( event : MouseEvent | TouchEvent ) : Point {
389
+ private _getPointerPositionInElement ( referenceElement : ElementRef < HTMLElement > ,
390
+ event : MouseEvent | TouchEvent ) : Point {
371
391
const elementRect = this . element . nativeElement . getBoundingClientRect ( ) ;
372
- const handleElement = this . _handle ? this . _handle . element . nativeElement : null ;
392
+ const handleElement = referenceElement === this . element ? null : referenceElement . nativeElement ;
373
393
const referenceRect = handleElement ? handleElement . getBoundingClientRect ( ) : elementRect ;
374
394
const x = this . _isTouchEvent ( event ) ? event . targetTouches [ 0 ] . pageX - referenceRect . left :
375
395
event . offsetX ;
0 commit comments