Ionic 2 - setting callback for “long press” event

2019-05-11 01:29发布

问题:

I am trying to add a custom longPress event directive on elements, since (press)="callback_function()" will result in ion-list won't be able to scroll anymore. Bug or not, i've found out that I need to add a custom gesture directive that would add support for a new attribute, in this case I call it longPress. and it works great, except I don't get how to add the callback function :-)

I've followed a tutorial (http://roblouie.com/article/198/using-gestures-in-the-ionic-2-beta/)

The "press-directive" is created in src/components/press-directive/press-directive.js and looks like this:

import { Directive, ElementRef, OnInit, OnDestroy } from '@angular/core';
import { Gesture } from "ionic-angular/gestures/gesture";

/**
 * Generated class for the PressDirective directive.
 *
 * See https://angular.io/docs/ts/latest/api/core/index/DirectiveMetadata-class.html
 * for more info on Angular Directives.
 */

@Directive({
  selector: '[longPress]' // Attribute selector
})


export class PressDirective implements OnInit, OnDestroy {
  el: HTMLElement;
  pressGesture: Gesture;

  constructor(el: ElementRef) {
    this.el = el.nativeElement;
  }

  public theCallback() {

  }

  ngOnInit() {
    this.pressGesture = new Gesture(this.el);
    this.pressGesture.listen();

    // instead of this..
    this.pressGesture.on('press', (event) => {
      console.log('pressed!!');
    });

    // i want the callback to come from the template like this:
    // <ion-col (longPress)="showActionSheet(object)">
  }

  ngOnDestroy() {
    this.pressGesture.destroy();
  }
}

In home.module.ts I have added the directive in an import:

import { PressDirective } from "../../components/press-directive/press-directive";

and I've added it in the declaration:

declarations: [
  Home,
  PressDirective
],

In home.html, I implement it in a like this:

<ion-col (longPress)="showActionSheet(relevantObject)">...

I've cut out most of the unimportant stuff :-)

And when I do a long press, it will return the following:

console.log('pressed!!');

But I can't get my head wrapped around how to support the actual callback function from the template element.

Any help or hint would be appreciated..

回答1:

For anyone who still has this problem, I ran into a very similar thing, and Steen's answer was very helpful in figuring out adding a callback.

However, I wanted to add a little clarification, because I think the distinction between "press" and "release" (or "pressup") should be made.

According to HammerJS docs (which ionic uses for Gestures), there is a "press" event, and also a "pressup" event, which is fired when the press is released.

You can actually include an @Output for each event (press and pressup):

/*
 * The first output will emit when the timeout is reached for press,
 * and the second will emit when the press gesture is released.
 */ 

@Output('long-press') onPress: EventEmitter<any> = new EventEmitter();
@Output('long-press-up') onPressUp: EventEmitter<any> = new EventEmitter();

Then, in the @ngOnInit, respond to each event with each respective emitter:**

this.pressGesture.on('press', (event) => {
  this.onPress.emit(event);
});

this.pressGesture.on('pressup', (event) => {
  this.onPressUp.emit(event);
});

This way, you can support a separate callback function for each gesture event (in the template/component):

<ion-col (long-press)="longPressed(object)" (long-press-up)="longPressReleased(object)">
  ...
</ion-col>

Hopefully that adds some info/clarity.



回答2:

Alright, so I was gently informed of the solution on the awesome ionic slack chat site (https://ionic-worldwide.slack.com) - I needed to use Output and EventEmitter

In the Import section, it had to look like this:

import { Directive, ElementRef, OnInit, OnDestroy, Output, EventEmitter } from '@angular/core';
import { Gesture } from "ionic-angular/gestures/gesture";

In the class, I had to add an @Output EventEmitter:

export class PressDirective implements OnInit, OnDestroy {
  el: HTMLElement;
  pressGesture: Gesture;
  @Output('long-press') onPressRelease: EventEmitter<any> = new EventEmitter();

And the on('press',...) inside ngOnInit had to look like this:

this.pressGesture.on('press', (event) => {
  this.onPressRelease.emit('released');
});

Now the template supports adding (long-press)="showActionSheet(object)":

<ion-col (long-press)="showActionSheet(object)">

And yes, I also changed it from longPress to long-press.. just looked better for me..



回答3:

I was able to resolve this issue in Ionic v4 by providing HAMMER_GESTURE_CONFIG in app module. Follow this link for the solution: Vertical scroll is not working with HammerJS and Angular2