Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Ionic 2 - setting callback for "long press" event directive

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

like image 854
Steen Kruse Avatar asked Feb 05 '23 15:02

Steen Kruse


2 Answers

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.

like image 131
tyguy Avatar answered Feb 11 '23 12:02

tyguy


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

like image 42
Steen Kruse Avatar answered Feb 11 '23 13:02

Steen Kruse