3

I've got an angular 7 website, and I want to add horizontal swipe to one component, and vertical swipe to another (the components are in the same module). I'm using hammerjs for that.

By default, hammerjs disables vertical swipe, so I enabled swipping in all directions with the code below.

export class MyHammerConfig extends HammerGestureConfig
{
  overrides = <any>{
    swipe: {direction: Hammer.DIRECTION_ALL},
  };
}

//declare provider in AppModule
providers: [
    {
      provide: HAMMER_GESTURE_CONFIG,
      useClass: MyHammerConfig
    }
]

The problem is vertical scrolling does not work on the component with the horizontal swipe. From what I've read, the solution is to add touch-action: pan-y in the component with the horizontal swipe.

However, this works on chrome but safari does not recognise the touch-action property.

My idea was to declare multiple providers for HAMMER_GESTURE_CONFIG, at the component level:

  • on the component with horizontal swipe, use a provider which only allows horizontal swipe
  • on the other one, only enable vertical swipe

However, component-level providers do not seem to take my providers into account.

Here is some code I tried to use to only enable horizontal swipe

export class HorizontalHammerConfig extends HammerGestureConfig
{
  overrides = <any>{
    swipe: {Hammer.DIRECTION_HORIZONTAL},
    pinch: {enable: false},
    rotate: {enable: false}
  };
}

//Component declaration
@Component({
  ...

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

Any idea?

Edit: Here is a stackblitz example demostrating the issue. The component level providers are ignored.

1
  • The two components in diferents modules?. But it's sound strange not work swipe. Are you check only a (swipe)="swipe($event)" and in the function discrimine if is a swipe down or swipe left?
    – Eliseo
    Commented Feb 14, 2020 at 15:51

1 Answer 1

3

I found the solution there.

Basically, the custom configuration has to override the buildHammer class, so different hammerjs options can be used depending on the context.

app.module.ts

export class MyHammerConfig extends HammerGestureConfig
{
  overrides = <any>{
    swipe: {direction: Hammer.DIRECTION_ALL},
  };

  buildHammer(element: HTMLElement)
  {
    let options = {};

    if (element.attributes['data-mc-options'])
    {
      try
      {
        options = JSON.parse(element.attributes['data-mc-options'].nodeValue);
      }
      catch (err)
      {
        console.error('An error occurred when attempting to parse Hammer.js options: ', err);
      }
    }

    const mc = new Hammer(element, options);


    // retain support for angular overrides object
    for (const eventName of Object.keys(this.overrides))
    {
      mc.get(eventName).set(this.overrides[eventName]);
    }

    return mc;
  }
}

And then, in the component template, pass the extra option as a json string.

component.html

<div (swipeleft)="onSwipeLeft()" data-mc-options='{ "touchAction": "pan-y" }'">
</div>

This works with safari/iOS

Not the answer you're looking for? Browse other questions tagged or ask your own question.