I have a component with click
.
<my-box (click)="openModal()"></my-box>
When I click this element, openModal
function will run. And I'd like to give 1000ms throttle time in order to prevent opening multiple modals.
My first approach was using Subject
(from rxJs)
//html <my-box (click)="someSubject$.next()"></my-box> //ts public someSubject$:Subject<any> = new Subject(); ...etc subscribe
But I feel it's a bit verbose.
Next Approach was using a directive
. I modified a bit of code that I found by googling.
//ts import {Directive, HostListener} from '@angular/core'; @Directive({ selector: '[noDoubleClick]' }) export class PreventDoubleClickDirective { constructor() { } @HostListener('click', ['$event']) clickEvent(event) { event.stopPropagation(); // not working as I expected. event.preventDefault(); // not working as I expected. event.srcElement.setAttribute('disabled', true); // it won't be working unless the element is input. event.srcElement.setAttribute('style', 'pointer-events: none;'); // test if 'pointer-events: none' is working but seems not. setTimeout(function () { event.srcElement.removeAttribute('disabled'); }, 500); } } //html <my-box noDoubleClick (click)="openModal()"></my-box>
However, whatever I try, always openModal
was executed. I couldn't find how to stop executing openModal
in the directive.
I can just make like
//ts //In the openModal method. openModal() { public isClickable = true setTimeout(() => { this.newsClickable = true; }, 1000); ... }
But for the reusable code, I think using directive is ideal.
How can I make it?
Present Code click(function (e) { // Prevent button from double click var isPageValid = Page_ClientValidate(); if (isPageValid) { if (isOperationInProgress == noIndicator) { isOperationInProgress = yesIndicator; } else { e.
The ng-dblclick directive tells AngularJS what to do when an HTML element is double-clicked. The ng-dblclick directive from AngularJS will not override the element's original ondblclick event, both are executed.
You can use RxJs' debounce or debounceTime operator to prevent double clicks. Here is also a post on how to create a custom debounce click directive.
In case the post is taken down in the future, here is the final code:
import { Directive, EventEmitter, HostListener, Input, OnDestroy, OnInit, Output } from '@angular/core'; import { Subject, Subscription } from 'rxjs'; import { debounceTime } from 'rxjs/operators'; @Directive({ selector: '[appDebounceClick]' }) export class DebounceClickDirective implements OnInit, OnDestroy { @Input() debounceTime = 500; @Output() debounceClick = new EventEmitter(); private clicks = new Subject(); private subscription: Subscription; constructor() { } ngOnInit() { this.subscription = this.clicks.pipe( debounceTime(this.debounceTime) ).subscribe(e => this.debounceClick.emit(e)); } ngOnDestroy() { this.subscription.unsubscribe(); } @HostListener('click', ['$event']) clickEvent(event) { event.preventDefault(); event.stopPropagation(); this.clicks.next(event); } }
<button appDebounceClick (debounceClick)="log()" [debounceTime]="700">Debounced Click</button>
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With