Skip to content

Commit b80b33b

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 e7b0e40 commit b80b33b

File tree

3 files changed

+52
-9
lines changed

3 files changed

+52
-9
lines changed

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

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

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

2843+
@Component({
2844+
changeDetection: ChangeDetectionStrategy.OnPush,
2845+
template: `
2846+
<div cdkDrag #dragElement style="width: 100px; height: 100px; background: red;"></div>
2847+
`
2848+
})
2849+
class StandaloneDraggableWithOnPush {
2850+
@ViewChild('dragElement') dragElement: ElementRef<HTMLElement>;
2851+
@ViewChild(CdkDrag) dragInstance: CdkDrag;
2852+
}
2853+
28242854
@Component({
28252855
template: `
28262856
<svg><g

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

Lines changed: 21 additions & 8 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, Observer, Subject, merge} from 'rxjs';
@@ -174,11 +175,12 @@ export class CdkDrag<T = any> implements AfterViewInit, OnChanges, OnDestroy {
174175
@Optional() private _dir: Directionality,
175176

176177
/**
177-
* @deprecated `viewportRuler` and `dragDropRegistry` parameters
178+
* @deprecated `viewportRuler`, `dragDropRegistry` and `_changeDetectorRef` parameters
178179
* to be removed. Also `dragDrop` parameter to be made required.
179180
* @breaking-change 8.0.0.
180181
*/
181-
dragDrop?: DragDrop) {
182+
dragDrop?: DragDrop,
183+
private _changeDetectorRef?: ChangeDetectorRef) {
182184

183185

184186
// @breaking-change 8.0.0 Remove null check once the paramter is made required.
@@ -191,7 +193,7 @@ export class CdkDrag<T = any> implements AfterViewInit, OnChanges, OnDestroy {
191193

192194
this._dragRef.data = this;
193195
this._syncInputs(this._dragRef);
194-
this._proxyEvents(this._dragRef);
196+
this._handleEvents(this._dragRef);
195197
}
196198

197199
/**
@@ -312,13 +314,17 @@ export class CdkDrag<T = any> implements AfterViewInit, OnChanges, OnDestroy {
312314
});
313315
}
314316

315-
/**
316-
* Proxies the events from a DragRef to events that
317-
* match the interfaces of the CdkDrag outputs.
318-
*/
319-
private _proxyEvents(ref: DragRef<CdkDrag<T>>) {
317+
/** Handles the events from the underlying `DragRef`. */
318+
private _handleEvents(ref: DragRef<CdkDrag<T>>) {
320319
ref.started.subscribe(() => {
321320
this.started.emit({source: this});
321+
322+
// Since all of these events run outside of change detection,
323+
// we need to ensure that everything is marked correctly.
324+
if (this._changeDetectorRef) {
325+
// @breaking-change 8.0.0 Remove null check for _changeDetectorRef
326+
this._changeDetectorRef.markForCheck();
327+
}
322328
});
323329

324330
ref.released.subscribe(() => {
@@ -327,6 +333,13 @@ export class CdkDrag<T = any> implements AfterViewInit, OnChanges, OnDestroy {
327333

328334
ref.ended.subscribe(() => {
329335
this.ended.emit({source: this});
336+
337+
// Since all of these events run outside of change detection,
338+
// we need to ensure that everything is marked correctly.
339+
if (this._changeDetectorRef) {
340+
// @breaking-change 8.0.0 Remove null check for _changeDetectorRef
341+
this._changeDetectorRef.markForCheck();
342+
}
330343
});
331344

332345
ref.entered.subscribe(event => {

tools/public_api_guard/cdk/drag-drop.d.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,7 @@ export declare class CdkDrag<T = any> implements AfterViewInit, OnChanges, OnDes
2828
constructor(
2929
element: ElementRef<HTMLElement>,
3030
dropContainer: CdkDropList, _document: any, _ngZone: NgZone, _viewContainerRef: ViewContainerRef, viewportRuler: ViewportRuler, dragDropRegistry: DragDropRegistry<DragRef, DropListRef>, config: DragRefConfig, _dir: Directionality,
31-
dragDrop?: DragDrop);
31+
dragDrop?: DragDrop, _changeDetectorRef?: ChangeDetectorRef | undefined);
3232
getPlaceholderElement(): HTMLElement;
3333
getRootElement(): HTMLElement;
3434
ngAfterViewInit(): void;

0 commit comments

Comments
 (0)