@@ -10,7 +10,7 @@ import {EmbeddedViewRef, ElementRef, NgZone, ViewContainerRef, TemplateRef} from
10
10
import { ViewportRuler } from '@angular/cdk/scrolling' ;
11
11
import { Directionality } from '@angular/cdk/bidi' ;
12
12
import { normalizePassiveListenerOptions } from '@angular/cdk/platform' ;
13
- import { coerceBooleanProperty } from '@angular/cdk/coercion' ;
13
+ import { coerceBooleanProperty , coerceElement } from '@angular/cdk/coercion' ;
14
14
import { Subscription , Subject , Observable , Observer } from 'rxjs' ;
15
15
import { DropListRefInternal as DropListRef } from './drop-list-ref' ;
16
16
import { DragDropRegistry } from './drag-drop-registry' ;
@@ -46,24 +46,10 @@ const activeEventListenerOptions = normalizePassiveListenerOptions({passive: fal
46
46
*/
47
47
const MOUSE_EVENT_IGNORE_TIME = 800 ;
48
48
49
- /**
50
- * Template that can be used to create a drag helper element (e.g. a preview or a placeholder).
51
- */
52
- interface DragHelperTemplate < T = any > {
53
- templateRef : TemplateRef < T > ;
54
- data : T ;
55
- }
56
-
57
- interface DragHandle {
58
- element : ElementRef < HTMLElement > ;
59
- disabled : boolean ;
60
- }
61
-
62
49
// TODO(crisbeto): add auto-scrolling functionality.
63
50
// TODO(crisbeto): add an API for moving a draggable up/down the
64
51
// list programmatically. Useful for keyboard controls.
65
52
66
-
67
53
/**
68
54
* Internal compile-time-only representation of a `DragRef`.
69
55
* Used to avoid circular import issues between the `DragRef` and the `DropListRef`.
@@ -187,13 +173,16 @@ export class DragRef<T = any> {
187
173
private _boundaryRect ?: ClientRect ;
188
174
189
175
/** Element that will be used as a template to create the draggable item's preview. */
190
- private _previewTemplate : DragHelperTemplate | null ;
176
+ private _previewTemplate ?: { template : TemplateRef < any > | null , context ?: any } ;
191
177
192
178
/** Template for placeholder element rendered to show where a draggable would be dropped. */
193
- private _placeholderTemplate : DragHelperTemplate | null ;
179
+ private _placeholderTemplate ?: { template : TemplateRef < any > | null , context ?: any } ;
194
180
195
181
/** Elements that can be used to drag the draggable item. */
196
- private _handles : DragHandle [ ] = [ ] ;
182
+ private _handles : HTMLElement [ ] = [ ] ;
183
+
184
+ /** Registered handles that are currently disabled. */
185
+ private _disabledHandles = new Set < HTMLElement > ( ) ;
197
186
198
187
/** Axis along which dragging is locked. */
199
188
lockAxis : 'x' | 'y' ;
@@ -292,36 +281,40 @@ export class DragRef<T = any> {
292
281
}
293
282
294
283
/** Registers the handles that can be used to drag the element. */
295
- withHandles ( handles : DragHandle [ ] ) : this {
296
- // TODO(crisbeto): have this accept HTMLElement[] | ElementRef<HTMLElement>[]
297
- this . _handles = handles ;
298
- handles . forEach ( handle => toggleNativeDragInteractions ( handle . element . nativeElement , false ) ) ;
284
+ withHandles ( handles : ( HTMLElement | ElementRef < HTMLElement > ) [ ] ) : this {
285
+ this . _handles = handles . map ( handle => coerceElement ( handle ) ) ;
286
+ this . _handles . forEach ( handle => toggleNativeDragInteractions ( handle , false ) ) ;
299
287
this . _toggleNativeDragInteractions ( ) ;
300
288
return this ;
301
289
}
302
290
303
- /** Registers the template that should be used for the drag preview. */
304
- withPreviewTemplate ( template : DragHelperTemplate | null ) : this {
305
- // TODO(crisbeto): have this accept a TemplateRef
306
- this . _previewTemplate = template ;
291
+ /**
292
+ * Registers the template that should be used for the drag preview.
293
+ * @param template Template that from which to stamp out the preview.
294
+ * @param context Variables to add to the template's context.
295
+ */
296
+ withPreviewTemplate ( template : TemplateRef < any > | null , context ?: any ) : this {
297
+ this . _previewTemplate = { template, context} ;
307
298
return this ;
308
299
}
309
300
310
- /** Registers the template that should be used for the drag placeholder. */
311
- withPlaceholderTemplate ( template : DragHelperTemplate | null ) : this {
312
- // TODO(crisbeto): have this accept a TemplateRef
313
- this . _placeholderTemplate = template ;
301
+ /**
302
+ * Registers the template that should be used for the drag placeholder.
303
+ * @param template Template that from which to stamp out the placeholder.
304
+ * @param context Variables to add to the template's context.
305
+ */
306
+ withPlaceholderTemplate ( template : TemplateRef < any > | null , context ?: any ) : this {
307
+ this . _placeholderTemplate = { template, context} ;
314
308
return this ;
315
309
}
316
310
317
-
318
311
/**
319
312
* Sets an alternate drag root element. The root element is the element that will be moved as
320
313
* the user is dragging. Passing an alternate root element is useful when trying to enable
321
314
* dragging on an element that you might not have access to.
322
315
*/
323
316
withRootElement ( rootElement : ElementRef < HTMLElement > | HTMLElement ) : this {
324
- const element = rootElement instanceof ElementRef ? rootElement . nativeElement : rootElement ;
317
+ const element = coerceElement ( rootElement ) ;
325
318
326
319
if ( element !== this . _rootElement ) {
327
320
if ( this . _rootElement ) {
@@ -340,8 +333,7 @@ export class DragRef<T = any> {
340
333
* Element to which the draggable's position will be constrained.
341
334
*/
342
335
withBoundaryElement ( boundaryElement : ElementRef < HTMLElement > | HTMLElement | null ) : this {
343
- this . _boundaryElement = boundaryElement instanceof ElementRef ?
344
- boundaryElement . nativeElement : boundaryElement ;
336
+ this . _boundaryElement = boundaryElement ? coerceElement ( boundaryElement ) : null ;
345
337
return this ;
346
338
}
347
339
@@ -370,6 +362,7 @@ export class DragRef<T = any> {
370
362
this . dropped . complete ( ) ;
371
363
this . _moveEvents . complete ( ) ;
372
364
this . _handles = [ ] ;
365
+ this . _disabledHandles . clear ( ) ;
373
366
this . _boundaryElement = this . _rootElement = this . _placeholderTemplate =
374
367
this . _previewTemplate = this . _nextSibling = null ! ;
375
368
}
@@ -386,6 +379,24 @@ export class DragRef<T = any> {
386
379
this . _passiveTransform = { x : 0 , y : 0 } ;
387
380
}
388
381
382
+ /**
383
+ * Sets a handle as disabled. While a handle is disabled, it'll capture and interrupt dragging.
384
+ * @param handle Handle element that should be disabled.
385
+ */
386
+ disableHandle ( handle : HTMLElement ) {
387
+ if ( this . _handles . indexOf ( handle ) > - 1 ) {
388
+ this . _disabledHandles . add ( handle ) ;
389
+ }
390
+ }
391
+
392
+ /**
393
+ * Enables a handle, if it has been disabled.
394
+ * @param handle Handle element to be enabled.
395
+ */
396
+ enableHandle ( handle : HTMLElement ) {
397
+ this . _disabledHandles . delete ( handle ) ;
398
+ }
399
+
389
400
/** Unsubscribes from the global subscriptions. */
390
401
private _removeSubscriptions ( ) {
391
402
this . _pointerMoveSubscription . unsubscribe ( ) ;
@@ -418,21 +429,19 @@ export class DragRef<T = any> {
418
429
this . _placeholder = this . _placeholderRef = null ! ;
419
430
}
420
431
421
-
422
432
/** Handler for the `mousedown`/`touchstart` events. */
423
433
private _pointerDown = ( event : MouseEvent | TouchEvent ) => {
424
434
this . beforeStarted . next ( ) ;
425
435
426
436
// Delegate the event based on whether it started from a handle or the element itself.
427
437
if ( this . _handles . length ) {
428
438
const targetHandle = this . _handles . find ( handle => {
429
- const element = handle . element . nativeElement ;
430
439
const target = event . target ;
431
- return ! ! target && ( target === element || element . contains ( target as HTMLElement ) ) ;
440
+ return ! ! target && ( target === handle || handle . contains ( target as HTMLElement ) ) ;
432
441
} ) ;
433
442
434
- if ( targetHandle && ! targetHandle . disabled && ! this . disabled ) {
435
- this . _initializeDragSequence ( targetHandle . element . nativeElement , event ) ;
443
+ if ( targetHandle && ! this . _disabledHandles . has ( targetHandle ) && ! this . disabled ) {
444
+ this . _initializeDragSequence ( targetHandle , event ) ;
436
445
}
437
446
} else if ( ! this . disabled ) {
438
447
this . _initializeDragSequence ( this . _rootElement , event ) ;
@@ -638,7 +647,8 @@ export class DragRef<T = any> {
638
647
639
648
// If we have a custom preview template, the element won't be visible anyway so we avoid the
640
649
// extra `getBoundingClientRect` calls and just move the preview next to the cursor.
641
- this . _pickupPositionInElement = this . _previewTemplate ? { x : 0 , y : 0 } :
650
+ this . _pickupPositionInElement = this . _previewTemplate && this . _previewTemplate . template ?
651
+ { x : 0 , y : 0 } :
642
652
this . _getPointerPositionInElement ( referenceElement , event ) ;
643
653
const pointerPosition = this . _pickupPositionOnPage = this . _getPointerPositionOnPage ( event ) ;
644
654
this . _pointerDirectionDelta = { x : 0 , y : 0 } ;
@@ -724,12 +734,12 @@ export class DragRef<T = any> {
724
734
* and will be used as a preview of the element that is being dragged.
725
735
*/
726
736
private _createPreviewElement ( ) : HTMLElement {
737
+ const previewTemplate = this . _previewTemplate ;
727
738
let preview : HTMLElement ;
728
739
729
- if ( this . _previewTemplate ) {
730
- const viewRef = this . _viewContainerRef . createEmbeddedView ( this . _previewTemplate . templateRef ,
731
- this . _previewTemplate . data ) ;
732
-
740
+ if ( previewTemplate && previewTemplate . template ) {
741
+ const viewRef = this . _viewContainerRef . createEmbeddedView ( previewTemplate . template ,
742
+ previewTemplate . context ) ;
733
743
preview = viewRef . rootNodes [ 0 ] ;
734
744
this . _previewRef = viewRef ;
735
745
preview . style . transform =
@@ -811,12 +821,13 @@ export class DragRef<T = any> {
811
821
812
822
/** Creates an element that will be shown instead of the current element while dragging. */
813
823
private _createPlaceholderElement ( ) : HTMLElement {
824
+ const placeholderTemplate = this . _placeholderTemplate ;
814
825
let placeholder : HTMLElement ;
815
826
816
- if ( this . _placeholderTemplate ) {
827
+ if ( placeholderTemplate && placeholderTemplate . template ) {
817
828
this . _placeholderRef = this . _viewContainerRef . createEmbeddedView (
818
- this . _placeholderTemplate . templateRef ,
819
- this . _placeholderTemplate . data
829
+ placeholderTemplate . template ,
830
+ placeholderTemplate . context
820
831
) ;
821
832
placeholder = this . _placeholderRef . rootNodes [ 0 ] ;
822
833
} else {
0 commit comments