Angular 2+ Directive for making an element un-clickable until the next tick
This directive will prevent clickable elements from being clicked again before the next ‘tick’. I hadn’t seen this particular solution in the wild, and it seems to be the most effective so it’s worth sharing.
If you want a DOM element to be covered up or otherwise disabled after being clicked, it may still be visible for a split second before the next round of change detection updates the DOM to do so.
A user with a fast clicky finger or tendency to double click everything even when it isn’t necessary could get an extra click in, causing an an unnecssary command. Especially frustrating if it’s a save button and two items are created instead of one.
stopPropogation() and preventDefault() functions on the click event were not effective in preventing all actions – however disabling pointer events via the style sheet was very effective in preventing errant clicks from registering. The clicked element is made un-clickable until the next tick via a 0 second setTimeout. Check out the full solution below.
import { Directive, HostListener } from '@angular/core';
@Directive({
selector: '[click],[type="submit"]',
})
export class ClickWaiterDirective {
constructor() { }
@HostListener("click", ["$event"])
public onClick(event: MouseEvent): void {
//Disable the target immediately after click
let targetElement = <HTMLElement>event.target;// Must cast as HTMLElement or style cannot be modified
targetElement.style.pointerEvents = 'none';// When css attribute pointer-events is set to 'none', the element becomes unclickable :)
//Only allow another click next 'tick' using setTimeout
setTimeout(()=>{
targetElement.style.pointerEvents = 'auto';// When css attribute pointer-events is set to 'auto', the element becomes clickable again
}, 0);
}
}
To use this, simply copy and paste the code into a new directive and reference it in your app.module.ts file. It will be applied to any form submit button or input, as well as any element with a (click) action