@@ -175,6 +175,9 @@ export class CdkDrag<T = any> implements AfterViewInit, OnDestroy {
175
175
/** Subscription to the event that is dispatched when the user lifts their pointer. */
176
176
private _pointerUpSubscription = Subscription . EMPTY ;
177
177
178
+ /** Subscription to the stream that initializes the root element. */
179
+ private _rootElementInitSubscription = Subscription . EMPTY ;
180
+
178
181
/** Elements that can be used to drag the draggable item. */
179
182
@ContentChildren ( CdkDragHandle , { descendants : true } ) _handles : QueryList < CdkDragHandle > ;
180
183
@@ -265,30 +268,36 @@ export class CdkDrag<T = any> implements AfterViewInit, OnDestroy {
265
268
// element to be in the proper place in the DOM. This is mostly relevant
266
269
// for draggable elements inside portals since they get stamped out in
267
270
// their original DOM position and then they get transferred to the portal.
268
- this . _ngZone . onStable . asObservable ( ) . pipe ( take ( 1 ) ) . subscribe ( ( ) => {
269
- const rootElement = this . _rootElement = this . _getRootElement ( ) ;
270
- rootElement . addEventListener ( 'mousedown' , this . _pointerDown , passiveEventListenerOptions ) ;
271
- rootElement . addEventListener ( 'touchstart' , this . _pointerDown , passiveEventListenerOptions ) ;
272
- toggleNativeDragInteractions ( rootElement , false ) ;
273
- } ) ;
271
+ this . _rootElementInitSubscription = this . _ngZone . onStable . asObservable ( )
272
+ . pipe ( take ( 1 ) )
273
+ . subscribe ( ( ) => {
274
+ const rootElement = this . _rootElement = this . _getRootElement ( ) ;
275
+ rootElement . addEventListener ( 'mousedown' , this . _pointerDown , passiveEventListenerOptions ) ;
276
+ rootElement . addEventListener ( 'touchstart' , this . _pointerDown , passiveEventListenerOptions ) ;
277
+ toggleNativeDragInteractions ( rootElement , false ) ;
278
+ } ) ;
274
279
}
275
280
276
281
ngOnDestroy ( ) {
277
- this . _rootElement . removeEventListener ( 'mousedown' , this . _pointerDown ,
278
- passiveEventListenerOptions ) ;
279
- this . _rootElement . removeEventListener ( 'touchstart' , this . _pointerDown ,
280
- passiveEventListenerOptions ) ;
281
- this . _destroyPreview ( ) ;
282
- this . _destroyPlaceholder ( ) ;
283
-
284
- // Do this check before removing from the registry since it'll
285
- // stop being considered as dragged once it is removed.
286
- if ( this . _isDragging ( ) ) {
287
- // Since we move out the element to the end of the body while it's being
288
- // dragged, we have to make sure that it's removed if it gets destroyed.
289
- this . _removeElement ( this . _rootElement ) ;
282
+ // The directive might have been destroyed before the root element is initialized.
283
+ if ( this . _rootElement ) {
284
+ this . _rootElement . removeEventListener ( 'mousedown' , this . _pointerDown ,
285
+ passiveEventListenerOptions ) ;
286
+ this . _rootElement . removeEventListener ( 'touchstart' , this . _pointerDown ,
287
+ passiveEventListenerOptions ) ;
288
+
289
+ // Do this check before removing from the registry since it'll
290
+ // stop being considered as dragged once it is removed.
291
+ if ( this . _isDragging ( ) ) {
292
+ // Since we move out the element to the end of the body while it's being
293
+ // dragged, we have to make sure that it's removed if it gets destroyed.
294
+ this . _removeElement ( this . _rootElement ) ;
295
+ }
290
296
}
291
297
298
+ this . _rootElementInitSubscription . unsubscribe ( ) ;
299
+ this . _destroyPreview ( ) ;
300
+ this . _destroyPlaceholder ( ) ;
292
301
this . _nextSibling = null ;
293
302
this . _dragDropRegistry . removeDragItem ( this ) ;
294
303
this . _removeSubscriptions ( ) ;
0 commit comments