djboardman
djboardman

Reputation: 162

Mouse Up event at the end of reactive drag and drop with Rxjs in Angular 2

I have the following, hopefully fairly standard, drag and drop code using Rxjs in Angular 2.

The blockElement happens to be an SVG rectangle but I don't think that makes any difference to the question.

I need to set the coordinates of the blockElement when it's finally dropped, i.e. when the mouseup event fires at the end of the drag. This is so that the user can drop it roughly in the right place and the code lines up its position correctly.

Can I achieve that by reacting to the takeUntil by running a function? Or is there some other Rxjs operator I can use to react to mouseup by running a function when it happens at the end of the drag?

(I've edited the code for clarity, but the actual code does work, so if there's any errors in what follows it shouldn't be relevant to the question and hopefully you get the idea)

const taskMouseDown$ = Observable.fromEvent(this.blockElement.nativeElement, 'mousedown');
const documentMouseUp$ = Observable.fromEvent(document, 'mouseup');
const documentMouseMove$ = Observable.fromEvent(document, 'mousemove');

const taskMouseDrag$ = taskMouseDown$.flatMap((mouseEvent: MouseEvent) => {
  return documentMouseMove$.map((mouseMoveEvent: MouseEvent) => {
    return ({mouseStart: mouseEvent, mouseCurrent: moveMouseEvent});
  }).takeUntil(documentMouseUp$);
});

taskMouseDrag$.subscribe(
  // Make the block element follow the mouse
});

Upvotes: 0

Views: 1727

Answers (2)

yurzui
yurzui

Reputation: 214037

1) You can use do operator like

.takeUntil(documentMouseUp$)
.do(
   () => {}, // next
   () => {}, // error
   () => {   // complete
    alert('mouseup')
   }
 );

or

declare module "rxjs/Observable" {
    interface Observable<T> {
        finish : typeof finish;
    }
}

function finish<T>(this : Observable<any>, fn: () => void): Observable<T> {
    return this.do(() => {}, () => {}, fn);
}

Observable.prototype.finish = finish;

...
.takeUntil(documentMouseUp$)
.finish(() => this.onMouseUp());

Plunker Example

2) Or you can just subscribe to documentMouseUp$

documentMouseUp$.subscribe(() => console.log('mouseup);

Upvotes: 1

Meir
Meir

Reputation: 14375

takeUntil terminates the stream when the condition is met and you can pass a handler for this:

takeMouseDrag$.subscribe(
  nextHandler, // your move handler
  completeHandler, // this gets triggered when the mouseup triggers the take until
  errorHandler // in case you want to handle errors
}

or in you case:

takeMouseDrag$.subscribe(
  onDrag,
  onDragEnd
)

Upvotes: 0

Related Questions