6

I am trying to avoid double clicks or double taps of button in ionic 4 as it should trigger action only on single click. If I double click, I want an action to be triggered once and not 2 times. I have tried several options such as disable button, settimeout but nothing worked. While searching for better solutions, I find many forums suggested debounceTime in Angular.

I followed the answer suggested in How to prevent double click in Angular? and tried to create a directive, but clicking of "debounceClick" gives me the below error.

ERROR Error: Uncaught (in promise): Error: Template parse errors:
Can't bind to 'debounceTime' since it isn't a known property of 'button'. ("
</ion-content>

<button appIonCLick (debounceClick)="log()" [ERROR ->][debounceTime]="700">Throttled Click</button>

The following is the directive I created

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


@Directive({
  selector: '[appIonCLick]'
})
export class IonCLickDirective 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);
  }
}

And below is the HTML

<button appIonCLick (debounceClick)="log()" [debounceTime]="700">Debounce Click</button> 

Can someone please help me if I am doing something wrong? I have no luck searching for debounceTime for ionic button click. Any help is appreciated!

  • did you declare the directive in respective module? – Pranav Ramachandran Dec 12 '19 at 19:55
  • Add the directive to your [shared module](https://angular.io/guide/sharing-ngmodules) and import the module where you want to use the directive. Also see: [How to declare a directive globally for all modules?](https://stackoverflow.com/q/41505392/9423231) – frido Dec 12 '19 at 20:18

3 Answers3

2
  1. Try to import the directive 'IonCLickDirective' in the declaration section of the module where you need to use this.
  2. <button appIonCLick (debounceClick)="log()" debounceTime="700">Debounce Click</button> try this [debounceTime] -> debounceTime
0

And it worked!

I had imported 'IonCLickDirective' in app.module.ts but not in the page component where I was using this directive IonCLickDirective. Once I removed it from app.module.ts and imported in declaration section in Page's component module.ts it works like a charm!

Also I tried the same using throttletime which works even better as it triggers action and waits instead of waiting and triggering incase of debounceTime!

Thanks a lot for helping me fix this which I was struggling for a week!

0

Just an improvement here for

    this.subscription = this.clicks.pipe(
      debounceTime(this.debounceTime), first()
    ).subscribe(e => this.debounceClick.emit(e));
  }

if we use first() then do not have the need to unsubscribe it. This is because it completes the chain and thus triggers dispose handlers.

NRP
  • 352
  • 4
  • 11