Swipeback Gesture Configuration in Ionic 4

August 23rd 2019 Ionic 4

Ionic has built-in support for navigating back using the swipe gesture. If you want to disable it for the whole application, you can pass a configuration option to IonicModule. The option has kept the same name Ionic 3 and Ionic 4:

IonicModule.forRoot({ swipeBackEnabled: false })

Alternatively, you can disable and re-enable swipeback navigation ar runtime. In Ionic 3, NavController exposed a property for that. You could easily inject NavController into a page and set the property value when entering and exiting the page:

constructor(public navCtrl: NavController) { }

ionViewDidEnter() {
  this.navCtrl.swipeBackEnabled = false;
}

ionViewDidLeave() {
  this.navCtrl.swipeBackEnabled = true;
}

In Ionic 4, this is a bit more complicated. NavController doesn't provide such a property anymore. Instead, IonRouterOutlet now has an equivalent swipeGesture property. However, you can't simply inject the IonRouterOutlet instance into a page. To work around this limitation, I created my own service which keeps a reference to the IonRouterOutlet and exposes its swipeGesture property:

import { Injectable } from '@angular/core';
import { IonRouterOutlet } from '@ionic/angular';

@Injectable({
  providedIn: 'root'
})
export class RouterOutletService {
  private routerOutlet: IonRouterOutlet;

  constructor() {}

  init(routerOutlet: IonRouterOutlet) {
    this.routerOutlet = routerOutlet;
  }

  get swipebackEnabled(): boolean {
    if (this.routerOutlet) {
      return this.routerOutlet.swipeGesture;
    } else {
      throw new Error('Call init() first!');
    }
  }

  set swipebackEnabled(value: boolean) {
    if (this.routerOutlet) {
      this.routerOutlet.swipeGesture = value;
    } else {
      throw new Error('Call init() first!');
    }
  }
}

In a page, I can now inject and use this service instead of NavController:

constructor( private routerOutletService: RouterOutletService) { }

ionViewDidEnter() {
  this.routerOutletService.swipebackEnabled = false;
}

ionViewDidLeave() {
  this.routerOutletService.swipebackEnabled = true;
}

For this to work, I have to initialize my service first by passing it the IonRouterOutlet instance. I do that in AppComponent where it's placed in the template:

@ViewChild(IonRouterOutlet, { static: false }) routerOutlet: IonRouterOutlet;

ngAfterViewInit(): void {
  this.routerOutletService.init(this.routerOutlet);
}

The current implementation only works with a single IonRouterInstance in the application but it can be enhanced with support for additional instances if you require that in your own application.

Copyright
Creative Commons License