Double Tap/ double click Angular2 & ionic
Asked Answered
R

6

14

I am searching on many forums and questions, but nobody seems to ask how to double click ou double tap in Angular/ionic 2 ?

In ionic v1 it was available with on-double-tap (see http://ionicframework.com/docs/api/directive/onDoubleTap/)

Does anyone maybe have a tip or any code to catch double click events on ionic 2 / angular 2?

Maybe through HammerJS?

Thank you very much ! Luis :)

Rickierickman answered 6/3, 2017 at 10:47 Comment(7)
not sure of double click.. but I think you could consider press eventAffirmative
I found it.. relatively easy : (dblclick)="myFunction()" from en.wikipedia.org/wiki/DOM_events#Events :)Rickierickman
ok.. not really sure how it would be useful in mobile deviceAffirmative
That's because you maybe don't know my application ? (dblclick) works on mobile, I tested.Rickierickman
ok..fair enough :)Affirmative
Haha thank you anyway ! Bye :)Rickierickman
Any solution for this now? dblclick doesn't work inside of ionicAstyanax
R
26

So after 1-2 hours it was obvious, you don't need to catch double click events with Ionic, but with pure JavaScript: dblclick()

So in Angular 2 it would be: (dblclick)="myFunction()" and that's it!

Here you will find other events for JavaScript.

Rickierickman answered 6/3, 2017 at 13:48 Comment(1)
Inorder for a generic implementation irrespective of the platform we need to write a custom directive of our own.Adsorbate
M
7

html file

<button (tap)="tapEvent()">Tap Me!</button>

ts file

let count : number = 0;
tapEvent(){
this.count++;
setTimeout(() => {
  if (this.count == 1) {
    this.count = 0;
    alert('Single Tap');
  }if(this.count > 1){
    this.count = 0;
    alert('Double Tap');
  }
}, 250);

}

Mcginnis answered 18/7, 2018 at 6:24 Comment(0)
K
4

To catch the double click event, the following can be used:

(dblclick)="clickFunction()"

If we want to fire a function on click and onother function on double click we can use the following:

<button (click)="simpleClickFunction()" (dblclick)="doubleClickFunction()">click me!</button>

However, the simpleClickFunction function will be called also when doubleClickFunction is fired. To prevent it to happen, setTimeout can help as the following:

html template

<button (click)="simpleClickFunction()" (dblclick)="doubleClickFunction()">click me!</button>

Component

simpleClickFunction(): void{
    this.timer = 0;
    this.preventSimpleClick = false;
    let delay = 200;

    this.timer = setTimeout(() => {
      if(!this.preventSimpleClick){
        //whatever you want with simple click go here
        console.log("simple click");
      }
    }, delay);

  }

  doubleClickFunction(): void{
    this.preventSimpleClick = true;
    clearTimeout(this.timer);
    //whatever you want with double click go here
    console.log("double click");
  }
Kookaburra answered 20/7, 2017 at 18:1 Comment(3)
Could the one who downvoted the question please explain why ?Kookaburra
I'm not the one who downvoted, but I guess it's because your answer doesn't add anything to the other answers and also because it's not addressing the major issue of multi platform compatibility. But again, it's just a guess.Elinaelinor
The answer has been upvoted by others. So the answer is useful for othersKookaburra
R
1

So.

  1. dbclick isn't working on smartphone.
  2. Using a library is actually the way to go

I found the solution on this gitHub repo

Directive

import { Directive, EventEmitter, Output, OnInit, HostListener } from '@angular/core';

@Directive({
  selector: '[appTap]'
})
export class TapDirective implements OnInit {

  @Output() tap = new EventEmitter();
  @Output() doubleTap = new EventEmitter();
  lastTap = 0;
  tapCount = 0;
  tapTimeout = null;
  tapGesture = {
    name: 'tap',
    enabled: false,
    interval: 250,
  };
  doubleTapGesture = {
    name: 'doubleTap',
    enabled: false,
    interval: 300,
  };

  constructor() { }

  ngOnInit(): void {
    this.tapGesture.enabled = true;
    this.doubleTapGesture.enabled = true;
  }

  @HostListener('click', ['$event'])
  handleTaps(e) {
    const tapTimestamp = Math.floor(e.timeStamp);
    const isDoubleTap = this.lastTap + this.tapGesture.interval > tapTimestamp;
    if (!this.tapGesture.enabled && !this.doubleTapGesture.enabled) {
      return this.resetTaps();
    }
    this.tapCount++;
    if (isDoubleTap && this.doubleTapGesture.enabled) {
      this.emitTaps();
    } else if (!isDoubleTap) {
      this.tapTimeout = setTimeout(() => this.emitTaps(), this.tapGesture.interval);
    }
    this.lastTap = tapTimestamp;
  }

  private emitTaps() {
    if (this.tapCount === 1 && this.tapGesture.enabled) {
      this.tap.emit();
    } else if (this.tapCount === 2 && this.doubleTapGesture.enabled) {
      this.doubleTap.emit();
    }
    this.resetTaps();
  }

  private resetTaps() {
    clearTimeout(this.tapTimeout); // clear the old timeout
    this.tapCount = 0;
    this.tapTimeout = null;
    this.lastTap = 0;
  }

}

Module

import { NgModule } from '@angular/core';
import { CommonModule } from '@angular/common';
import { TapDirective } from './tap/tap.directive';
import { PressDirective } from './press/press.directive';
import { SwipeDirective } from './swipe/swipe.directive';
import { GestureDirective } from './gesture/gesture.directive';

@NgModule({
  declarations: [
    TapDirective,
  ],
  imports: [
    CommonModule
  ],
  exports: [
    TapDirective,
  ]
})
export class TapDirectiveModule { }
<div appTap (doubleTap)="doSomething()"

There you go..

Tips: I did let the tap logic, remove it if not needed

Richmound answered 1/3, 2023 at 9:34 Comment(1)
This is pretty good. One thing, it could be improved by adding @Input() mobileOnly: 'true' | 'false' | boolean = false;, and a check if Event instanceof PointerEvent :)Bank
S
0

Ionic 2 has basic gestures which can be accessed from HTML. Should work on iOS and Android. You can find the documentation here.

The source code provided by them is here.

Smyrna answered 26/6, 2017 at 19:29 Comment(1)
The link to gestures is now here: ionicframework.com/docs/utilities/gesturesDowncome
A
0

For capturing generic gesture, I created the following to handle double click, long press and short swipe and release.

Make sure to import the GestureController from Ionic Angular

longPressStartedTime;

constructor(
        private gestureController: GestureController,
        ) { }

Create a class on the elements we want to attach the gesture handling to

<div class="long-pressable">
some content here...
</div>

Then create the gesture handling code handler

   let pressableElements = this.elementRef.nativeElement.querySelectorAll('.long-pressable') as any[];

    for(let i = 0; i < pressableElements.length; i++) {
      const gesture = this.gestureController.create({
        el: pressableElements[i],
        gestureName: 'long-press',
        threshold: 0,
        onStart: ev => {

          // double click
          if(this.longPressStartedTime && ((new Date().getTime() - this.longPressStartedTime) < 300)) {
            this.doubleClickMessage(this.chatMessages[i]);
          }
          this.longPressStartedTime = new Date().getTime();
          console.log("start")
        },
        onMove: ev => {
          //console.log("move", ev);
          if(ev.deltaX > 0 && ev.deltaX < 40) {
            pressableElements[i].style.transform = `translateX(${ev.deltaX}px)`;
          }
        },        
        onEnd: ev => {
          let longPressEllapsed = new Date().getTime() - this.longPressStartedTime;
          console.log("long press ended", longPressEllapsed)
          pressableElements[i].style.transform = `translateX(0px)`;

          if(ev.deltaX > 30) {
            this.handleSwipe(this.chatMessages[i]);
          }
          else if(longPressEllapsed > 500) {
this.handleLongPress()
          }
        }
      });
      gesture.enable(true);
      pressableElements[i].addEventListener('contextmenu', (evt) => {evt.preventDefault()});
    }
Analphabetic answered 6/12, 2021 at 14:8 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.