The ability to reply to discussions is limited to PRO members. Want to join in the discussion? Click here to subscribe now.

Use an event stream of double clicks in RxJS

Use an event stream of double clicks in RxJS

4:36
See a practical example of reactive programming in JavaScript and the DOM. Learn how to detect double clicks with a few operators in RxJS. We will use `.bufferWhen` to accumulate events into an array to determine if a double click occurred.
Watch this lesson now
Avatar
egghead.io

See a practical example of reactive programming in JavaScript and the DOM. Learn how to detect double clicks with a few operators in RxJS.

Avatar
Kevin

Why not just an actual button?

In reply to egghead.io
Avatar
Michele Mendel

I downloaded RxJS v4 and the double-click doesn't register. Switching to v2.3.22 - using https://cdnjs.cloudflare.com/ajax/libs/rxjs/2.3.22/rx.all.js - the example started work.

Avatar
Michele Mendel

Using v4 you need to use debounce instead of throttle

Avatar
Niklas

Cool, I'm not the first to stumble on the throttle/debounce thing. Thanks for already having it answered here :)

Avatar
Richard Hoffmann

+1 for thanks :)

In reply to Michele Mendel
Avatar
Igor

How this code can be modified, so the doubleClick stream emits rightaway and not after 250ms delay?

Avatar
Niels Kristian Hansen Skovmand

Remember to use debounce()
instead
of throttle()

-- see the code examples on the page.

Avatar
Dominic Watson

Just subscribed to pro and not cool to see out of date tutorials. Using 5-beta I expected something not to work, but this tutorial running on 2 is ancient. The JSBin itself references 4 and doesn't even work.

Avatar
Andre

Thanks Dominic for reporting this. We fixed the JSBin example by changing the use of throttle() to delay(), because in older versions of RxJS, throttle used to have some delaying behavior too.

In reply to Dominic Watson
Avatar
Rafael

I spent quite some time trying to figure out how to do the same thing with the latest version of RxJS (5.0.0-beta.10) so I'd like to share here how I got it working:

const single$ = Rx.Observable.fromEvent(button, 'click');
single$
    .bufferWhen(() => single$.debounceTime(250))
    .map(list => list.length)
    .filter(length => length >= 2)
    .subscribe(totalClicks => {
        console.log(`multi clicks total: ${totalClicks}`);
    });

Thanks for this intro course Andre and please let me know if there's something wrong with this implementation or if there's a better way to do the same thing.

In reply to Andre
Avatar
PJ

Here is the version which works on rxjs 5.x:

const timeout = 250;
const clicks$ = Rx.Observable.fromEvent(button, "click");
const doubleClicks$ = clicks$
    .map(() => new Date())
    .bufferCount(2, 1)
    .map(([prev, next]) => (next - prev) < timeout)
    .scan((prev, next) => !prev && next, false)
    .filter(v => v)
In reply to Rafael
Avatar
Kostiantyn

Would work with that code too:

doubleClickStream = clickStream
    .bufferWhen(() => clickStream.debounceTime(250))
    .filter(arr => arr.length === 2);
Avatar
Shaun

That's what I ended up with in v5 too. I'm still bothered by the fact that the 250 ms delay applies even after the second click. Native double click events fire at mouse up, not 250 ms later.

In reply to Kostiantyn
Avatar
Vincent

@Kostiantyn that's what I found out after much time researching the doc (at least now I know what the doc looks like :) ) @andre: maybe a foreword that the library is changing a lot and that your code isn't up to date with the latest version would help.

In reply to Kostiantyn
Avatar
Vincent

@shaun that's necessary if you want to rule out "triple clicks". If you don't, and want to fire immediately after the second click, @PJ 's implementation works well

In reply to Shaun
HEY, QUICK QUESTION!
Joel's Head
Why are we asking?