mirror of
https://github.com/angular/angular.git
synced 2026-09-14 13:54:52 +08:00
feat(drag-drop): add released event (#14513)
Adds the `cdkDragReleased` event, in addition to `cdkDragEnded`. The difference between released and ended is that released will fire as soon as the user has released the item, whereas ended will fire once all animations are done. The former is useful to customize the animation on drop, based on where the item is being dropped. Fixes #14498.
This commit is contained in:
committed by
Jeremy Elbourn
parent
c94812de2c
commit
792d536580
@@ -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();
|
||||
@@ -1221,6 +1222,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();
|
||||
@@ -2597,6 +2632,7 @@ describe('CdkDrag', () => {
|
||||
cdkDrag
|
||||
[cdkDragBoundary]="boundarySelector"
|
||||
(cdkDragStarted)="startedSpy($event)"
|
||||
(cdkDragReleased)="releasedSpy($event)"
|
||||
(cdkDragEnded)="endedSpy($event)"
|
||||
#dragElement
|
||||
style="width: 100px; height: 100px; background: red;"></div>
|
||||
@@ -2608,6 +2644,7 @@ class StandaloneDraggable {
|
||||
@ViewChild(CdkDrag) dragInstance: CdkDrag;
|
||||
startedSpy = jasmine.createSpy('started spy');
|
||||
endedSpy = jasmine.createSpy('ended spy');
|
||||
releasedSpy = jasmine.createSpy('released spy');
|
||||
boundarySelector: string;
|
||||
}
|
||||
|
||||
|
||||
@@ -38,6 +38,7 @@ import {
|
||||
CdkDragExit,
|
||||
CdkDragMove,
|
||||
CdkDragStart,
|
||||
CdkDragRelease,
|
||||
} from '../drag-events';
|
||||
import {CdkDragHandle} from './drag-handle';
|
||||
import {CdkDragPlaceholder} from './drag-placeholder';
|
||||
@@ -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>();
|
||||
|
||||
@@ -254,6 +259,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});
|
||||
});
|
||||
|
||||
@@ -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. */
|
||||
|
||||
@@ -213,6 +213,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}>();
|
||||
|
||||
@@ -355,6 +358,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();
|
||||
@@ -516,6 +520,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
|
||||
|
||||
+5
@@ -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(
|
||||
@@ -92,6 +93,10 @@ export declare class CdkDragPreview<T = any> {
|
||||
constructor(templateRef: TemplateRef<T>);
|
||||
}
|
||||
|
||||
export interface CdkDragRelease<T = any> {
|
||||
source: CdkDrag<T>;
|
||||
}
|
||||
|
||||
export interface CdkDragSortEvent<T = any, I = T> {
|
||||
container: CdkDropList<T>;
|
||||
currentIndex: number;
|
||||
|
||||
Reference in New Issue
Block a user