Skip to content

Commit 31dc628

Browse files
committed
fix(drag-drop): standalone draggable drag class not being applied with OnPush change detection
Fixes the styling that is applied while an item is dragged not being applied with `OnPush` change detection.
1 parent 98711d7 commit 31dc628

File tree

2 files changed

+51
-7
lines changed

2 files changed

+51
-7
lines changed

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

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -460,6 +460,25 @@ describe('CdkDrag', () => {
460460
expect(element.classList).not.toContain('cdk-drag-dragging');
461461
}));
462462

463+
it('should add a class while an element is being dragged with OnPush change detection',
464+
fakeAsync(() => {
465+
const fixture = createComponent(StandaloneDraggableWithOnPush);
466+
fixture.detectChanges();
467+
468+
const element = fixture.componentInstance.dragElement.nativeElement;
469+
470+
expect(element.classList).not.toContain('cdk-drag-dragging');
471+
472+
startDraggingViaMouse(fixture, element);
473+
474+
expect(element.classList).toContain('cdk-drag-dragging');
475+
476+
dispatchMouseEvent(document, 'mouseup');
477+
fixture.detectChanges();
478+
479+
expect(element.classList).not.toContain('cdk-drag-dragging');
480+
}));
481+
463482
it('should not add a class if item was not dragged more than the threshold', fakeAsync(() => {
464483
const fixture = createComponent(StandaloneDraggable, [], 5);
465484
fixture.detectChanges();
@@ -2705,6 +2724,17 @@ class StandaloneDraggable {
27052724
boundarySelector: string;
27062725
}
27072726

2727+
@Component({
2728+
changeDetection: ChangeDetectionStrategy.OnPush,
2729+
template: `
2730+
<div cdkDrag #dragElement style="width: 100px; height: 100px; background: red;"></div>
2731+
`
2732+
})
2733+
class StandaloneDraggableWithOnPush {
2734+
@ViewChild('dragElement') dragElement: ElementRef<HTMLElement>;
2735+
@ViewChild(CdkDrag) dragInstance: CdkDrag;
2736+
}
2737+
27082738
@Component({
27092739
template: `
27102740
<svg><g

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

Lines changed: 21 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,7 @@ import {
2828
ViewContainerRef,
2929
OnChanges,
3030
SimpleChanges,
31+
ChangeDetectorRef,
3132
} from '@angular/core';
3233
import {coerceBooleanProperty} from '@angular/cdk/coercion';
3334
import {Observable, Subscription, Observer} from 'rxjs';
@@ -171,7 +172,9 @@ export class CdkDrag<T = any> implements AfterViewInit, OnChanges, OnDestroy {
171172
private _viewportRuler: ViewportRuler,
172173
private _dragDropRegistry: DragDropRegistry<DragRef, DropListRef>,
173174
@Inject(CDK_DRAG_CONFIG) private _config: DragRefConfig,
174-
@Optional() private _dir: Directionality) {
175+
@Optional() private _dir: Directionality,
176+
// @breaking-change 8.0.0 _changeDetectorRef parameter to be made required.
177+
private _changeDetectorRef?: ChangeDetectorRef) {
175178

176179
const ref = this._dragRef = new DragRef(element, this._document, this._ngZone,
177180
this._viewContainerRef, this._viewportRuler, this._dragDropRegistry,
@@ -188,7 +191,7 @@ export class CdkDrag<T = any> implements AfterViewInit, OnChanges, OnDestroy {
188191
.withPreviewTemplate(this._previewTemplate);
189192
}
190193
});
191-
this._proxyEvents(ref);
194+
this._handleEvetns(ref);
192195
}
193196

194197
/**
@@ -261,13 +264,17 @@ export class CdkDrag<T = any> implements AfterViewInit, OnChanges, OnDestroy {
261264
return selector ? getClosestMatchingAncestor(this.element.nativeElement, selector) : null;
262265
}
263266

264-
/**
265-
* Proxies the events from a DragRef to events that
266-
* match the interfaces of the CdkDrag outputs.
267-
*/
268-
private _proxyEvents(ref: DragRef<CdkDrag<T>>) {
267+
/** Handles the events from the underlying `DragRef`. */
268+
private _handleEvetns(ref: DragRef<CdkDrag<T>>) {
269269
ref.started.subscribe(() => {
270270
this.started.emit({source: this});
271+
272+
// Since all of these events run outside of change detection,
273+
// we need to ensure that everything is marked correctly.
274+
if (this._changeDetectorRef) {
275+
// @breaking-change 8.0.0 Remove null check for _changeDetectorRef
276+
this._changeDetectorRef.markForCheck();
277+
}
271278
});
272279

273280
ref.released.subscribe(() => {
@@ -276,6 +283,13 @@ export class CdkDrag<T = any> implements AfterViewInit, OnChanges, OnDestroy {
276283

277284
ref.ended.subscribe(() => {
278285
this.ended.emit({source: this});
286+
287+
// Since all of these events run outside of change detection,
288+
// we need to ensure that everything is marked correctly.
289+
if (this._changeDetectorRef) {
290+
// @breaking-change 8.0.0 Remove null check for _changeDetectorRef
291+
this._changeDetectorRef.markForCheck();
292+
}
279293
});
280294

281295
ref.entered.subscribe(event => {

0 commit comments

Comments
 (0)