Ionic-framework: [Ionic v4] Hammer disappeared

Created on 26 Jul 2018  路  21Comments  路  Source: ionic-team/ionic-framework

Ionic Info
@ionic/angular: "4.0.0-beta.0"

Describe the Bug
There used to be Hammer in package 'ionic-angular/gestures/hammer'. It disappeared.

Expected solution
Put it back or provide guidance about how to migrate in the breaking changes list (should we simply import it ourselves? or should we rely on something else?)

core

Most helpful comment

So I just gonna let that here because I spent at least 10 hours on the following problem till I figured a solution thx 脿 la v3

I was facing the following problem: Some ion-list and ion-scroll weren't scrollable only on iOS. After a lot of time I finally figured out that these elements were freezing because they weren't contained in an element where I use the (swipe) event

Why it's related to this event? I include hammers in my app because it isn't provided anymore in v4. Turns out in v3, hammerjs was not only provided but was also configured in ionic to handle that problem (reference: https://github.com/angular/angular/issues/10541 and code: https://github.com/ionic-team/ionic/commit/174efc196d7f234e64b1cedc05b49065dd0d2be5#diff-2b61e9589c57aeb2cfa7206751477cfe)

Anyhow to solve this in v4, create a provider like:

 import {Injectable} from '@angular/core';
 import {HammerGestureConfig} from '@angular/platform-browser';

 /**
  * @hidden
  * This class overrides the default Angular gesture config.
  */
 @Injectable()
 export class IonicGestureConfig extends HammerGestureConfig {
     buildHammer(element: HTMLElement) {
         const mc = new (<any> window).Hammer(element);

         for (const eventName in this.overrides) {
             if (eventName) {
                 mc.get(eventName).set(this.overrides[eventName]);
             }
         }

         return mc;
     }

 }

and inject it in your app.module.ts

 providers: [
    {provide: HAMMER_GESTURE_CONFIG, useClass: IonicGestureConfig}
 ]

enjoy scroll and swipe on iOS ;)

All 21 comments

Just saw the following warning msg in my console, don't know exactly why/where etc. but it's probably related to this

core.js:3129 The "swipe" event cannot be bound because Hammer.JS is not loaded and no custom loader has been specified.

So I just gonna let that here because I spent at least 10 hours on the following problem till I figured a solution thx 脿 la v3

I was facing the following problem: Some ion-list and ion-scroll weren't scrollable only on iOS. After a lot of time I finally figured out that these elements were freezing because they weren't contained in an element where I use the (swipe) event

Why it's related to this event? I include hammers in my app because it isn't provided anymore in v4. Turns out in v3, hammerjs was not only provided but was also configured in ionic to handle that problem (reference: https://github.com/angular/angular/issues/10541 and code: https://github.com/ionic-team/ionic/commit/174efc196d7f234e64b1cedc05b49065dd0d2be5#diff-2b61e9589c57aeb2cfa7206751477cfe)

Anyhow to solve this in v4, create a provider like:

 import {Injectable} from '@angular/core';
 import {HammerGestureConfig} from '@angular/platform-browser';

 /**
  * @hidden
  * This class overrides the default Angular gesture config.
  */
 @Injectable()
 export class IonicGestureConfig extends HammerGestureConfig {
     buildHammer(element: HTMLElement) {
         const mc = new (<any> window).Hammer(element);

         for (const eventName in this.overrides) {
             if (eventName) {
                 mc.get(eventName).set(this.overrides[eventName]);
             }
         }

         return mc;
     }

 }

and inject it in your app.module.ts

 providers: [
    {provide: HAMMER_GESTURE_CONFIG, useClass: IonicGestureConfig}
 ]

enjoy scroll and swipe on iOS ;)

thanks @peterpeterparker
Ionic team, any confirmation of that?

@peterpeterparker Would you please share a whole code example on using gestures with Ionic/Angular in v4 ? In v3 I was using the Gesture class provided by ionic-angular with three Hammer recognizers. Now I am lost: I can't find any information in the migration guide and I'm scratching my head...

@ptitjes d茅sol茅 for my late answer, unfortunately I don't use Gesture therefore can't share any code :(

@peterpeterparker Thanks anyway. I finally used Hammer by including it in my main.ts. It seems to add all the events to every elements. I don't know whether this is efficient but that seems to work anyway !

@ptitjes cool 馃憤

just in case, if you notice that some ion-list or div which would not be scrollable anymore on iOS because you added hammerjs, the tricks above should solves it

@peterpeterparker Yes, thank you ! I integrated it in my code :) (I had not envision the migration to v4 would be so painful... :/)

I must say it's pretty painful indeed; after 48 hours working on migrating my app, I've abandoned; too many APIs missing, too many breaking changes not documented (and too many bugs, but that's understandable for a beta).

on this particular topic, I'd still appreciate a confirmation of the Ionic team about the right way to go. My fear indeed is that, by adding Hammer to the project, every event is captured twice, with a negative impact on performance

@gklasen I would discourage the use of any external JS script in an Ionic application

  • 1st, it's a mobile app, not a website => it's supposed to work offline
  • 2nd, external scripts are loaded asynchronously; while it's not loaded, anything you do with Hammer won't work

if you want to use hammer in your mobile app, add hammer in your node_modules, as any library you use

So do the ionic core team have something to say about this? What path should we follow?
Thanks guys

@manucorporat

@giacomocerquone, I don't know what the official stance is on the matter. However, here is how I managed to handle gestures cleanly with @ionic/angular.

You can import hammerjs in your project and use it directly.

import Hammer from 'hammerjs';

@Component({
  // ...
})
export class MyComponentUsingGestures implements OnInit, OnDestroy {

  constructor(private elementRef: ElementRef) {}

  ngOnInit() {
    let element = this.elementRef.nativeElement;
    this._hammer = new Hammer.Manager(element, {
      recognizers: [
        [Hammer.Pan, { direction: Hammer.DIRECTION_VERTICAL }],
        [Hammer.Press],
        [Hammer.Tap],
      ],
    });

    this._hammer.on('pan', this.pan);
    this._hammer.on('press', this.press);
    this._hammer.on('pressup', this.pressup);
    this._hammer.on('tap', this.tap);
  }

  ngOnDestroy() {
    if (this._hammer) {
      this._hammer.off('pan', this.pan);
      this._hammer.off('press', this.press);
      this._hammer.off('pressup', this.pressup);
      this._hammer.off('tap', this.tap);

      this._hammer.destroy();
      this._hammer = null;
    }
  }

  // ...
}

One important thing to notice is that you have to register a custom HammerGestureConfig, as explained by @peterpeterparker in the comment above so that it plays well with Ionic.

Yeah yeah i did the same thing, the point is that without that fix posted above, my app seems to go well with an ion list for example, I couldn't try it on an iPhone though... so I should put it just to stay safe? It feels a little bit wrong
Also I don't use this.native.element that is kinda wrong but viewchild on the div i want to control with hammer, could be that?

I've just got the same warning re. lack of hammerjs when setting a press handler. It seems strange that the framework code knows what it wants, but searching the framework's website shows no related results outside the forum, where there seems to be no official word.

I could make hammer.js work - and also ionic with material.angular.io (in the bottom)

Hammer + ionic:
npm install --save hammerjs
npm install --save @types/hammerjs

  • package.json
    make sure in dependencies there is this line
    "hammerjs": "^2.0.8",

  • tsconfig.json - added types as seen below

"compilerOptions": {
...
...
"types": [
"hammerjs"
]
}

  • in app.component.ts
    import 'hammerjs';
    (only there)

in html file
div id="myElement">

in .ts file
Sample code from hammerjs site works
let element2 = document.getElementById('myElement');

let hamming = new Hammer(element2);
hamming.on("panleft panright tap press pressup", function(ev) {
element2.textContent = ev.type +" gesture detected.";
console.log(ev.type +" gesture detected.");
});

Hammer+ionic+material:
to make material hammer work with ionic

in app.module
import { HAMMER_GESTURE_CONFIG } from '@angular/platform-browser';
import { GestureConfig } from '@angular/material';
providers: [
{ provide: HAMMER_GESTURE_CONFIG, useClass: GestureConfig },
]

and voila, your material slider works.

They introduced also a new GestureController and Gesture in https://github.com/ionic-team/ionic/tree/master/core/src/utils/gesture

Did someone try to get work this in your app? I thinks they intend to export this and we can use a new type of GestureController to do anything we wan't to do.

@mburger81 I may be wrong, but I believe none of that is publicly exported.

Yes but until now there is a breaking change on all hammerjs wrapped events in ionic3, which I think should not be for the final Release.
Also there is an open issue from Mike which should be a remeber to export anything
Also I read many time ago they are happy with the new gesture controller and they would write a post about it.

Any news on this topic ?
I am able to listen to event by importing hammerjs the following way, but impossible to stop the propagation of the event.. any ideas ?

import Hammer from 'hammerjs';


 let element = this.elementRef.nativeElement;
 var hammertime = new Hammer(element);
 hammertime.domEvents = true;
 hammertime.on("press", (e) => {
            e.srcEvent.stopPropagation();
            e.srcEvent.preventDefault();
            e.srcEvent.stopImmediatePropagation();
            // e.gesture.stopPropagation();  // do not exist anymore
            // e.gesture.preventDefault(); // do not exist anymore
});

Hammerjs will not be provided by Ionic by default, but it can be added to your angular project: https://blog.angularindepth.com/gestures-in-an-angular-application-dde71804c0d0

We will add extensive guides of how to do it soon, but it's not something will be add by default in order to keep bundle as small and fast as possible!

https://blog.angularindepth.com/gestures-in-an-angular-application-dde71804c0d0

Thanks for the issue! This issue is being locked to prevent comments that are not relevant to the original issue. If this is still an issue with the latest version of Ionic, please create a new issue and ensure the template is fully filled out.

Was this page helpful?
0 / 5 - 0 ratings

Related issues

masimplo picture masimplo  路  3Comments

manucorporat picture manucorporat  路  3Comments

BilelKrichen picture BilelKrichen  路  3Comments

giammaleoni picture giammaleoni  路  3Comments

gio82 picture gio82  路  3Comments