How to handle hybrid devices in click/touch events properly?

You could use a Subject and debounce for a couple of milliseconds so you only have one event, something like this:

import {Component, Renderer} from '@angular/core'
import { Subject } from 'rxjs/Subject';
import 'rxjs/add/operator/debounceTime';

@Component({
  selector: 'my-app',
  template: `
    <div>
      <h2>Hello {{name}}</h2>
    </div>
  `,
})
export class App {
  name = 'Angular2';
  subject = new Subject();
  
  constructor(renderer: Renderer) {
    renderer.listenGlobal('document', 'touchend', (e) => {
      console.log('touchend');
      this.subject.next(e);
    });
    renderer.listenGlobal('document', 'click', (e) => {
      console.log('click');
      this.subject.next(e);
    });

    this.subject.debounceTime(100).subscribe(event => {
      console.log(event); //do stuff here
    })
  }
}

So when you use hybrid devices, you will get this: enter image description here

Two events were fired, but you only get one on your Observable.

You can play around in this plunker


Just add (tap) directive instead of (click) directive on your components and add hammerjs to your index.html file.

Angular 2 will do all the job for you.

Example:

<my-component (tap)="doSomething()"></my-component>

On your index.html add:

<script src="hammer.min.js"></script>

To get hammerjs

npm install hammerjs --save

With this the click and the tap will work fine. If you want to have more control over the tap or you want to bind events to your element on runtime try something like this.

_hammerEvents: HammerManager;

public bindTapEvent(element: ElementRef):void{
    this._hammerEvents = new Hammer(element.nativeElement);
    this._hammerEvents.on("tap", (event:any) => { /* do something */});
}