ionic-team / ionic-framework

A powerful cross-platform UI toolkit for building native-quality iOS, Android, and Progressive Web Apps with HTML, CSS, and JavaScript.
https://ionicframework.com
MIT License
51.09k stars 13.51k forks source link

[Ionic v4] Hammer disappeared #14883

Closed cvaliere closed 5 years ago

cvaliere commented 6 years ago

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?)

peterpeterparker commented 6 years ago

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.

peterpeterparker commented 6 years ago

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 ;)

cvaliere commented 6 years ago

thanks @peterpeterparker Ionic team, any confirmation of that?

ptitjes commented 6 years ago

@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...

peterpeterparker commented 6 years ago

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

ptitjes commented 6 years ago

@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 !

peterpeterparker commented 6 years ago

@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

ptitjes commented 6 years ago

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

cvaliere commented 6 years ago

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

cvaliere commented 6 years ago

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

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

giacomocerquone commented 6 years ago

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

@manucorporat

ptitjes commented 6 years ago

@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.

giacomocerquone commented 6 years ago

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?

leegee commented 6 years ago

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.

diver2 commented 6 years ago

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

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

in html file div id="myElement"></div

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.

mburger81 commented 5 years ago

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.

ptitjes commented 5 years ago

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

mburger81 commented 5 years ago

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.

ostno commented 5 years ago

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
});
manucorporat commented 5 years ago

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

ionitron-bot[bot] commented 5 years ago

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.