Have you ever wanted your app to behave differently on single-clicking and double-clicking? Sounds like an easy one to implement right? Wrong!
The issue is that the browser also interprets a double click as two single clicks and causes BOTH your event handlers to fire causing bloodshed and destruction 😭
We can neatly solve this problem by using the power of RxJs Subjects and preventing event bubbling using an ergonomic directive:
- We have moved our click handling strategy into a directive so that we can reuse it easily on any DOM node in our Angular template
- We have declared a
Subjectto hold the stream of our click events
- By binding to both events using
HostListenerthe directive, we prevent the bubbling and default behaviour of these events and pump the event into our clicks subject
- The problem is that both
dblclickevents bubble upwards so on double-clicking, the single click handler will fire twice and then the double click handler will fire once. We need to stop this bubbling!
- The browser specs guarantee the order of the
dblclickevent always occurring AFTER the
clickevent. So, by using the
debounceTimeoperator we can control the “speed” of the double-clicking. This will help us differentiate between
dblclickevents. After the debounce window, if the value emitted by the clicks subject is not a double click, then it is definitely a single click.
- The `selector` of this directive also matches the output event names. This makes our usage API ergonomic and succinct as seen below:
// In some angular template bind to events `click.single` and `click.double`
<div (click.single)="onSingleClick($event)" (click.double)="onDoubleClick(event)">
I got 99 problems but the click ain't one
And we’re done 🎉🎉🎉
Hope you found this useful