What is the best way to implement swipe navigation in Angular 2?

For the swipe detection here is a simpler solution than adding HammerJS:

In app.component.html:

<div (touchstart)="swipe($event, 'start')" (touchend)="swipe($event, 'end')">
  App content here
</div>

In app.component.ts:

private swipeCoord?: [number, number];
private swipeTime?: number;

swipe(e: TouchEvent, when: string): void {
  const coord: [number, number] = [e.changedTouches[0].clientX, e.changedTouches[0].clientY];
  const time = new Date().getTime();

  if (when === 'start') {
    this.swipeCoord = coord;
    this.swipeTime = time;
  } else if (when === 'end') {
    const direction = [coord[0] - this.swipeCoord[0], coord[1] - this.swipeCoord[1]];
    const duration = time - this.swipeTime;

    if (duration < 1000 //
      && Math.abs(direction[0]) > 30 // Long enough
      && Math.abs(direction[0]) > Math.abs(direction[1] * 3)) { // Horizontal enough
        const swipe = direction[0] < 0 ? 'next' : 'previous';
        // Do whatever you want with swipe
    }
  }
}

Note: I tried the HammerJS solution but configuring it to ignore mouse gestures was impossible because you don't have direct access to the Hammer object. So selecting some text was forcing navigation to the next page...


You can use HammerJS to implement for touch actions, You can follow this plunker for example.

Include hammer.js file

<script src="https://cdnjs.cloudflare.com/ajax/libs/hammer.js/2.0.8/hammer.js"></script>

or

npm install hammerjs --save

For browser touch support with hammerjs, include

 <script src="http://cdn.rawgit.com/hammerjs/touchemulator/master/touch-emulator.js"></script>
<script>

Import in app.module.ts

import { HammerGestureConfig, HAMMER_GESTURE_CONFIG } from '@angular/platform-browser';

export class MyHammerConfig extends HammerGestureConfig  {
  overrides = <any>{
    'swipe': {velocity: 0.4, threshold: 20} // override default settings
  }
}

@NgModule({
  imports: [BrowserModule],
  declarations: [AppComponent],
  bootstrap: [AppComponent],
  providers: [{ 
    provide: HAMMER_GESTURE_CONFIG, 
    useClass: MyHammerConfig 
  }] // use our custom hammerjs config
})

plunker link for example

To implement tabs angular2-material is a good place to start, follow this link


I created a directive from @Elvis Metodiev answer and @pikiou :

swipe.directive.ts

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

@Directive({ selector: '[swipe]' })
export class SwipeDirective {

    @Output() next = new EventEmitter<void>();
    @Output() previous = new EventEmitter<void>();

    swipeCoord = [0, 0];
    swipeTime = new Date().getTime();

    constructor() { }

    @HostListener('touchstart', ['$event']) onSwipeStart($event) {
        this.onSwipe($event, 'start');
    }

    @HostListener('touchend', ['$event']) onSwipeEnd($event) {
        this.onSwipe($event, 'end');
    }

    onSwipe(e: TouchEvent, when: string) {
        this.swipe(e, when);
    }

    swipe(e: TouchEvent, when: string): void {

        const coord: [number, number] = [e.changedTouches[0].clientX, e.changedTouches[0].clientY];
        const time = new Date().getTime();

        if (when === 'start') {
            this.swipeCoord = coord;
            this.swipeTime = time;
        } else if (when === 'end') {
            const direction = [coord[0] - this.swipeCoord[0], coord[1] - this.swipeCoord[1]];
            const duration = time - this.swipeTime;

            if (duration < 1000 //
                && Math.abs(direction[0]) > 30 // Long enough
                && Math.abs(direction[0]) > Math.abs(direction[1] * 3)) { // Horizontal enough
                const swipeDir = direction[0] < 0 ? 'next' : 'previous';
                if (swipeDir === 'next') {
                    this.next.emit();
                } else {
                    this.previous.emit();
                }
            }
        }
    }
}

tour.component.component.ts

<div
  ...
  swipe
  (next)="onRotateNext()"
  (previous)="onRotatePrevious()"
>
...
</div>

First install hammerjs and action touch-action polyfill:

$ npm install hammerjs hammer-timejs

Then add the imports to 'app.module.ts' so they will be used/bundled:

import 'hammerjs';
import 'hammer-timejs';

Now you can handle the events for the actions:
Rotate
Pinch
Press
Pan
Tap
Swipe

For example you can say:

<li *ngFor="let employee of employeesList;" (swiperight)="myswiperight(employee)" (swipeleft)="myswipeleft(employee)">

Or:

<div (panstart)="onPanStart($event)" (panmove)="onPan($event)">

Reference: https://saschwarz.github.io/angular2-gestures-slides/#/