mirror of
https://github.com/angular/angular.git
synced 2026-09-14 13:54:52 +08:00
fix(drag-drop): drop list not toggling dragging class inside component with OnPush change detection (#13703)
Fixes the `CdkDropList` not toggling its `cdk-drop-list-dragging` class if it's placed inside a component with `OnPush` change detection. Fixes #13680.
This commit is contained in:
committed by
Jeremy Elbourn
parent
d0d97c3e37
commit
12c15ba999
@@ -9,6 +9,7 @@ import {
|
||||
ViewChild,
|
||||
ViewChildren,
|
||||
ViewEncapsulation,
|
||||
ChangeDetectionStrategy,
|
||||
} from '@angular/core';
|
||||
import {TestBed, ComponentFixture, fakeAsync, flush, tick} from '@angular/core/testing';
|
||||
import {DragDropModule} from './drag-drop-module';
|
||||
@@ -547,6 +548,27 @@ describe('CdkDrag', () => {
|
||||
expect(dropZone.element.nativeElement.classList).not.toContain('cdk-drop-dragging');
|
||||
}));
|
||||
|
||||
it('should toggle a class when the user starts dragging an item with OnPush change detection',
|
||||
fakeAsync(() => {
|
||||
const fixture = createComponent(DraggableInOnPushDropZone);
|
||||
fixture.detectChanges();
|
||||
const item = fixture.componentInstance.dragItems.toArray()[1].element.nativeElement;
|
||||
const dropZone = fixture.componentInstance.dropInstance;
|
||||
|
||||
expect(dropZone.element.nativeElement.classList).not.toContain('cdk-drop-list-dragging');
|
||||
|
||||
startDraggingViaMouse(fixture, item);
|
||||
|
||||
expect(dropZone.element.nativeElement.classList).toContain('cdk-drop-list-dragging');
|
||||
|
||||
dispatchMouseEvent(document, 'mouseup');
|
||||
fixture.detectChanges();
|
||||
flush();
|
||||
fixture.detectChanges();
|
||||
|
||||
expect(dropZone.element.nativeElement.classList).not.toContain('cdk-drop-dragging');
|
||||
}));
|
||||
|
||||
it('should not toggle dragging class if the element was not dragged more than the threshold',
|
||||
fakeAsync(() => {
|
||||
const fixture = createComponent(DraggableInDropZone, [], 5);
|
||||
@@ -1991,24 +2013,24 @@ class StandaloneDraggableWithMultipleHandles {
|
||||
@ViewChildren(CdkDragHandle) handles: QueryList<CdkDragHandle>;
|
||||
}
|
||||
|
||||
@Component({
|
||||
template: `
|
||||
const DROP_ZONE_FIXTURE_TEMPLATE = `
|
||||
<div
|
||||
cdkDropList
|
||||
style="width: 100px; background: pink;"
|
||||
[id]="dropZoneId"
|
||||
[cdkDropListData]="items"
|
||||
(cdkDropListDropped)="droppedSpy($event)">
|
||||
<div
|
||||
cdkDropList
|
||||
style="width: 100px; background: pink;"
|
||||
[id]="dropZoneId"
|
||||
[cdkDropListData]="items"
|
||||
(cdkDropListDropped)="droppedSpy($event)">
|
||||
<div
|
||||
*ngFor="let item of items"
|
||||
cdkDrag
|
||||
[cdkDragData]="item"
|
||||
[style.height.px]="item.height"
|
||||
[style.margin-bottom.px]="item.margin"
|
||||
style="width: 100%; background: red;">{{item.value}}</div>
|
||||
</div>
|
||||
`
|
||||
})
|
||||
*ngFor="let item of items"
|
||||
cdkDrag
|
||||
[cdkDragData]="item"
|
||||
[style.height.px]="item.height"
|
||||
[style.margin-bottom.px]="item.margin"
|
||||
style="width: 100%; background: red;">{{item.value}}</div>
|
||||
</div>
|
||||
`;
|
||||
|
||||
@Component({template: DROP_ZONE_FIXTURE_TEMPLATE})
|
||||
class DraggableInDropZone {
|
||||
@ViewChildren(CdkDrag) dragItems: QueryList<CdkDrag>;
|
||||
@ViewChild(CdkDropList) dropInstance: CdkDropList;
|
||||
@@ -2024,6 +2046,12 @@ class DraggableInDropZone {
|
||||
});
|
||||
}
|
||||
|
||||
@Component({
|
||||
template: DROP_ZONE_FIXTURE_TEMPLATE,
|
||||
changeDetection: ChangeDetectionStrategy.OnPush,
|
||||
})
|
||||
class DraggableInOnPushDropZone extends DraggableInDropZone {}
|
||||
|
||||
|
||||
@Component({
|
||||
encapsulation: ViewEncapsulation.None,
|
||||
|
||||
@@ -28,7 +28,7 @@ import {
|
||||
SkipSelf,
|
||||
ViewContainerRef,
|
||||
} from '@angular/core';
|
||||
import {supportsPassiveEventListeners} from '@angular/cdk/platform';
|
||||
import {normalizePassiveListenerOptions} from '@angular/cdk/platform';
|
||||
import {Observable, Subject, Subscription, Observer} from 'rxjs';
|
||||
import {take} from 'rxjs/operators';
|
||||
import {DragDropRegistry} from './drag-drop-registry';
|
||||
@@ -80,8 +80,7 @@ export function CDK_DRAG_CONFIG_FACTORY(): CdkDragConfig {
|
||||
}
|
||||
|
||||
/** Options that can be used to bind a passive event listener. */
|
||||
const passiveEventListenerOptions = supportsPassiveEventListeners() ?
|
||||
{passive: true} as EventListenerOptions : false;
|
||||
const passiveEventListenerOptions = normalizePassiveListenerOptions({passive: true});
|
||||
|
||||
/** Element that can be moved inside a CdkDropList container. */
|
||||
@Directive({
|
||||
|
||||
@@ -19,6 +19,7 @@ import {
|
||||
QueryList,
|
||||
Optional,
|
||||
Directive,
|
||||
ChangeDetectorRef,
|
||||
} from '@angular/core';
|
||||
import {Directionality} from '@angular/cdk/bidi';
|
||||
import {CdkDrag} from './drag';
|
||||
@@ -141,6 +142,7 @@ export class CdkDropList<T = any> implements OnInit, OnDestroy {
|
||||
constructor(
|
||||
public element: ElementRef<HTMLElement>,
|
||||
private _dragDropRegistry: DragDropRegistry<CdkDrag, CdkDropList<T>>,
|
||||
private _changeDetectorRef: ChangeDetectorRef,
|
||||
@Optional() private _dir?: Directionality) {}
|
||||
|
||||
ngOnInit() {
|
||||
@@ -175,6 +177,7 @@ export class CdkDropList<T = any> implements OnInit, OnDestroy {
|
||||
this._dragging = true;
|
||||
this._activeDraggables = this._draggables.toArray();
|
||||
this._cachePositions();
|
||||
this._changeDetectorRef.markForCheck();
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
Reference in New Issue
Block a user