Skip to content

feat(drag-drop): add released event #14513

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 1 commit into from
Dec 18, 2018
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
37 changes: 37 additions & 0 deletions src/cdk/drag-drop/directives/drag.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -354,6 +354,7 @@ describe('CdkDrag', () => {
dragElementViaMouse(fixture, fixture.componentInstance.dragElement.nativeElement, 2, 2);

expect(fixture.componentInstance.startedSpy).not.toHaveBeenCalled();
expect(fixture.componentInstance.releasedSpy).not.toHaveBeenCalled();
expect(fixture.componentInstance.endedSpy).not.toHaveBeenCalled();
expect(moveSpy).not.toHaveBeenCalled();
subscription.unsubscribe();
Expand Down Expand Up @@ -1169,6 +1170,40 @@ describe('CdkDrag', () => {
.toBeFalsy('Expected preview to be removed from the DOM if the transition timed out');
}));

it('should emit the released event as soon as the item is released', fakeAsync(() => {
const fixture = createComponent(DraggableInDropZone);
fixture.detectChanges();
const item = fixture.componentInstance.dragItems.toArray()[1];
const endedSpy = jasmine.createSpy('ended spy');
const releasedSpy = jasmine.createSpy('released spy');
const endedSubscription = item.ended.subscribe(endedSpy);
const releasedSubscription = item.released.subscribe(releasedSpy);

startDraggingViaMouse(fixture, item.element.nativeElement);

const preview = document.querySelector('.cdk-drag-preview')! as HTMLElement;

// Add a duration since the tests won't include one.
preview.style.transitionDuration = '500ms';

// Move somewhere so the draggable doesn't exit immediately.
dispatchMouseEvent(document, 'mousemove', 50, 50);
fixture.detectChanges();

dispatchMouseEvent(document, 'mouseup');
fixture.detectChanges();

// Expected the released event to fire immediately upon release.
expect(releasedSpy).toHaveBeenCalled();
tick(1000);

// Expected the ended event to fire once the entire sequence is done.
expect(endedSpy).toHaveBeenCalled();

endedSubscription.unsubscribe();
releasedSubscription.unsubscribe();
}));

it('should reset immediately when failed drag happens after a successful one', fakeAsync(() => {
const fixture = createComponent(DraggableInDropZone);
fixture.detectChanges();
Expand Down Expand Up @@ -2459,6 +2494,7 @@ describe('CdkDrag', () => {
cdkDrag
[cdkDragBoundary]="boundarySelector"
(cdkDragStarted)="startedSpy($event)"
(cdkDragReleased)="releasedSpy($event)"
(cdkDragEnded)="endedSpy($event)"
#dragElement
style="width: 100px; height: 100px; background: red;"></div>
Expand All @@ -2470,6 +2506,7 @@ class StandaloneDraggable {
@ViewChild(CdkDrag) dragInstance: CdkDrag;
startedSpy = jasmine.createSpy('started spy');
endedSpy = jasmine.createSpy('ended spy');
releasedSpy = jasmine.createSpy('released spy');
boundarySelector: string;
}

Expand Down
9 changes: 9 additions & 0 deletions src/cdk/drag-drop/directives/drag.ts
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,7 @@ import {
CdkDragExit,
CdkDragMove,
CdkDragStart,
CdkDragRelease,
} from '../drag-events';
import {CdkDragHandle} from './drag-handle';
import {CdkDragPlaceholder} from './drag-placeholder';
Expand Down Expand Up @@ -118,6 +119,10 @@ export class CdkDrag<T = any> implements AfterViewInit, OnDestroy {
/** Emits when the user starts dragging the item. */
@Output('cdkDragStarted') started: EventEmitter<CdkDragStart> = new EventEmitter<CdkDragStart>();

/** Emits when the user has released a drag item, before any animations have started. */
@Output('cdkDragReleased') released: EventEmitter<CdkDragRelease> =
new EventEmitter<CdkDragRelease>();

/** Emits when the user stops dragging an item in the container. */
@Output('cdkDragEnded') ended: EventEmitter<CdkDragEnd> = new EventEmitter<CdkDragEnd>();

Expand Down Expand Up @@ -255,6 +260,10 @@ export class CdkDrag<T = any> implements AfterViewInit, OnDestroy {
this.started.emit({source: this});
});

ref.released.subscribe(() => {
this.released.emit({source: this});
});

ref.ended.subscribe(() => {
this.ended.emit({source: this});
});
Expand Down
6 changes: 6 additions & 0 deletions src/cdk/drag-drop/drag-events.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,12 @@ export interface CdkDragStart<T = any> {
source: CdkDrag<T>;
}

/** Event emitted when the user releases an item, before any animations have started. */
export interface CdkDragRelease<T = any> {
/** Draggable that emitted the event. */
source: CdkDrag<T>;
}

/** Event emitted when the user stops dragging a draggable. */
export interface CdkDragEnd<T = any> {
/** Draggable that emitted the event. */
Expand Down
6 changes: 6 additions & 0 deletions src/cdk/drag-drop/drag-ref.ts
Original file line number Diff line number Diff line change
Expand Up @@ -207,6 +207,9 @@ export class DragRef<T = any> {
/** Emits when the user starts dragging the item. */
started = new Subject<{source: DragRef}>();

/** Emits when the user has released a drag item, before any animations have started. */
released = new Subject<{source: DragRef}>();

/** Emits when the user stops dragging an item in the container. */
ended = new Subject<{source: DragRef}>();

Expand Down Expand Up @@ -349,6 +352,7 @@ export class DragRef<T = any> {
this._removeSubscriptions();
this.beforeStarted.complete();
this.started.complete();
this.released.complete();
this.ended.complete();
this.entered.complete();
this.exited.complete();
Expand Down Expand Up @@ -506,6 +510,8 @@ export class DragRef<T = any> {
return;
}

this.released.next({source: this});

if (!this.dropContainer) {
// Convert the active transform into a passive one. This means that next time
// the user starts dragging the item, its position will be calculated relatively
Expand Down
5 changes: 5 additions & 0 deletions tools/public_api_guard/cdk/drag-drop.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ export declare class CdkDrag<T = any> implements AfterViewInit, OnDestroy {
exited: EventEmitter<CdkDragExit<any>>;
lockAxis: 'x' | 'y';
moved: Observable<CdkDragMove<T>>;
released: EventEmitter<CdkDragRelease>;
rootElementSelector: string;
started: EventEmitter<CdkDragStart>;
constructor(
Expand Down Expand Up @@ -92,6 +93,10 @@ export declare class CdkDragPreview<T = any> {
constructor(templateRef: TemplateRef<T>);
}

export interface CdkDragRelease<T = any> {
source: CdkDrag<T>;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Extra indent

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This file is auto-generated.

}

export interface CdkDragSortEvent<T = any, I = T> {
container: CdkDropList<T>;
currentIndex: number;
Expand Down