How to prevent double click in Angular?

故事扮演 提交于 2019-12-04 03:21:12

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:

Directive:

import { Directive, EventEmitter, HostListener, Input, OnDestroy, OnInit, 
Output } from '@angular/core';
import { Subject } from 'rxjs/Subject';
import { Subscription } from 'rxjs/Subscription';
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);
  }
}

Example Usage:

<button appDebounceClick (debounceClick)="log()" [debounceTime]="700">Debounced Click</button>

In my case throttleTime instead of debounce was better solution(fire event immediately and block until some time passed)

Since some people asked for the throttleTime directive, I'll add it below. I chose to go this route because the debounceTime waits for the last click before firing the actual click event. throttleTime will not allow the clicker to click the button again until that time is reached and instead fires the click event immediately.

Directive

import { Directive, EventEmitter, HostListener, Input, OnDestroy, OnInit, Output } from '@angular/core';
import { Subject, Subscription } from 'rxjs';
import { throttleTime } from 'rxjs/operators';

@Directive({
  selector: '[appPreventDoubleClick]'
})
export class PreventDoubleClickDirective implements OnInit, OnDestroy {
  @Input()
  throttleTime = 500;

  @Output()
  throttledClick = new EventEmitter();

  private clicks = new Subject();
  private subscription: Subscription;

  constructor() { }

  ngOnInit() {
    this.subscription = this.clicks.pipe(
      throttleTime(this.throttleTime)
    ).subscribe(e => this.emitThrottledClick(e));
  }

  emitThrottledClick(e) {
    this.throttledClick.emit(e);
  }

  ngOnDestroy() {
    this.subscription.unsubscribe();
  }

  @HostListener('click', ['$event'])
  clickEvent(event) {
    event.preventDefault();
    event.stopPropagation();
    this.clicks.next(event);
  }
}

Example Usage

throttleTime is optional since there is a default of 500 in the directive

<button appPreventDoubleClick (throttledClick)="log()" [throttleTime]="700">Throttled Click</button>

If you have a bot that's clicking on your element every 1ms, then you'll notice that the event only ever fires once until the throttleTime is up.

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!