Angular Application: How to Add Swiping with NgRx

by | Jul 29, 2019

Swiping left and right, up and down is so common a use case that it is vital that you as a developer add it to your toolbox.  This article will focus on adding left/right swiping to an Angular application using NgRx. Using NgRx here isn’t vital but makes it easier to do with multiple components.

I wrote a simple recipe application that has 3 terrible recipes for pies – to allow for swiping between them.  You can find the code and app here on Stackblitz:

 

Dependencies

The only dependency to install for swiping is hammerjs.  As of this writing, it is at version 2.0.8. It is important, however, to add your own config file so that you only get left/right or horizontal swiping (or whatever it is for your requirements.)

 

I called my custom config file my-hammer.config.ts:

 

import { HammerGestureConfig } from "@angular/platform-browser";
import * as hammer from "hammerjs";
 
export class MyHammerConfig extends HammerGestureConfig {
  overrides = <any>{
    swipe: { direction: hammer.DIRECTION_HORIZONTAL },
    pinch: { enable: false },
    rotate: { enable: false }
  };
}

Note the following:

 

  • HammerGestureConfig is an Angular class but it is very much tied to HammerJS
  • hammer.DIRECTION_HORIZONTAL is used to get left/right swiping
    • Want to ignore vertical or up/down swiping since we may have to scroll and that would take out scrolling
  • Disable pinch and rotate since we don’t care about those gestures

Add this config file to app.module in the providers as follows:

 

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

Handling Swiping Events

HammerJS adds the following events for swiping:

 

  • swipeleft
  • swiperight
  • swipeup
  • swipedown

Simply add them to your main content section as shown here in app.component.html:

 

<div (swipeleft)="swipeLeft()"
     (swiperight)="swipeRight()"
     class="main-content">
  <h1>Add Swiping to Angular Application</h1>
  <app-current-recipe></app-current-recipe>
</div>

Note the following:

 

  • swipeup/swipedown would not be handled here since the config didn’t include vertical swiping
  • The main-content css class allows the user to swipe the “blank” content area (below the last component on the page) and still get the swiping events
    • Without this, swiping would not occur in this area
    • This is vital to remember as phone/tablet users would expect that blank area to work

.main-content {
  height: 100vh;
}

  • The swiping methods that are called are simply dispatching NgRx actions:

  swipeLeft() {
    this.store.dispatch(new appActions.SwipeLeft());
  }
 
  swipeRight() {
    this.store.dispatch(new appActions.SwipeRight());
  }

  • This is done so that the components that care about swiping can respond in whatever way they want
  • The actions are not handled in the reducer or the effect, but in the component (keep reading and you’ll discover how)
  • Also, using NgRx is optional. You can handle swiping events however you want.

Listening for NgRx Swiping Actions with Angular Applications

So far we’ve added hammerjs swiping to the application but it isn’t doing anything with those events.  Time to fix that.

 

The application has two components:

 

  • CurrentRecipeComponent – has the list of recipes and maintains the current index into this list to show it so we are seeing one recipe at a time
  • RecipeComponent – shows the details of the recipe

The CurrentRecipeComponent is the one that will listen for NgRx swiping actions because it must alter the current index based on whether they swiped left or right.  It will listen for the actions using the NgRx ActionsSubject. This Subject is notified for every action that is dispatched in NgRx. So, I am basically using NgRx as a pub/sub pattern.  Subscribing only to the actions I care about in a given component.

 

Here is the code:

 

  constructor(private actionsSubject: ActionsSubject) {}
 
  ngOnInit() {
    this.actionsSubject
      .pipe(
        filter((action: Action) => {
          return (
            action.type === AppActionTypes.SwipeLeft ||
            action.type === AppActionTypes.SwipeRight
          );
        }),ActionsSubject is injected into the constructor
In the ngOnInit, I filter the actions to only those I care about (SwipeLeft & SwipeRight)
  • Call nextRecipe() if the user swipes left
  • Call previousRecipe() if the user swipes right

Here is the code for next/previousRecipe:

 

  nextRecipe() {
    if (this.currentIndex < this.recipes.length - 1) {
      this.currentIndex++;
    } else {
      this.currentIndex = 0;
    }
  }
 
  previousRecipe() {
    if (this.currentIndex > 0) {
      this.currentIndex--;
    } else {
      this.currentIndex = this.recipes.length - 1;
    }
  }

Note that I am going to the first recipe once the user tries to swipe left (nextRecipe called) on the last recipe.  I’m also going to the last recipe once the user tries to swipe right (previousRecipe called) on the first recipe.

 

You can test this on Stackblitz by clicking your mouse and holding as you swipe left or right and letting go of the click at the end of the swipe.  It should cycle through the recipes nicely.

 

 

Why NgRx is Nice to use for Swiping in Angular Applications

So, it seems like using NgRx in this example is overkill but it’s really not.

 

Consider this scenario:

 

  • Requirements change and now we want instructions to be an array of strings
    • Also, view one instruction at a time
  • Show the current instruction and then allow swiping left or right to see the next/previous instruction
    • Now the current instruction component can listen for the same ActionsSubject actions to be dispatched and handle showing the next or previous instruction

As you can clearly see, there is no need to re-invent the wheel each time you need swiping in your app.  All you have to do is listen for the NgRx swiping actions and you’re gold.

 

 

Conclusion

Adding swiping to your Angular application is quite easy with hammerjs.  With just a few NgRx actions dispatched to handle the swipeleft and swiperight events, any component in your application can now handle swiping with ease.  It’s time to bring your web application up to speed with mobile devices and handle swiping like a pro!