Swipeback Gesture Configuration in 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.