14

I have developed a PWA (Tab based) using Ionic 3. It is working fine until hardware back button or browser's back button is pressed in android browser. If it is running from home screen, pressing hardware back will close app. If app is running in chrome in android (only tested in chrome), hardware back or browser's back will reload PWA's first page, not previously visited page. How to handle these events in Ionic 3 PWA?

I am using lazy load for all pages.

What I tried so far:

  1. As per jgw96's comment here, I thought IonicPage will handle navigation itself. But it is not working.

  2. Used platform.registerBackButtonAction, but it's not for PWA.

  3. As per Webruster's suggestion below in Answers, tried code in app.component.ts. But no change.

Posting code:

    import { Component, ViewChild } from '@angular/core';
    import { Nav, Platform, AlertController, Alert, Events, App, IonicApp, MenuController } from 'ionic-angular';

    @Component({
      templateUrl: 'app.html'
    })
    export class MyApp {
      @ViewChild(Nav) nav: Nav;
      rootPage:any = 'TabsPage';
      constructor(public platform: Platform,
        public alertCtrl: AlertController, public events: Events,
          public menu: MenuController,
          private _app: App,
          private _ionicApp: IonicApp) {

        platform.ready().then(() => {
          this.configureBkBtnprocess ();
        });
      }

      configureBkBtnprocess() {
        if (window.location.protocol !== "file:") {
          window.onpopstate = (evt) => {
            if (this.menu.isOpen()) {
              this.menu.close ();
              return;
            }
    let activePortal = this._ionicApp._loadingPortal.getActive() ||
      this._ionicApp._modalPortal.getActive() ||
      this._ionicApp._toastPortal.getActive() ||
      this._ionicApp._overlayPortal.getActive();

    if (activePortal) {
      activePortal.dismiss();
      return;
    }

    if (this._app.getRootNav().canGoBack())
      this._app.getRootNav().pop();
          };

          this._app.viewDidEnter.subscribe((app) => {
            history.pushState (null, null, "");
            });
        }
      }
    }
Krsna Kishore
  • 8,233
  • 4
  • 32
  • 48
Vivek Sinha
  • 1,556
  • 1
  • 13
  • 24

2 Answers2

7

you have mentioned that you are working with the hardware back button on app and in browser so you didn't mention clearly what need to be done at what stage so i came up with the generalized solution which can be useful in most of the cases

app.component.ts

platform.ready().then(() => {

      // your other plugins code...
      this.configureBkBtnprocess ();

    });

configureBkBtnprocess

private configureBkBtnprocess () {

    // If you are on chrome (browser)
    if (window.location.protocol !== "file:") {

      // Register browser back button action and you can perform
      // your own actions like as follows
      window.onpopstate = (evt) => {

        // Close menu if open
        if (this._menu.isOpen()) {
          this._menu.close ();
          return;
        }

        // Close any active modals or overlays
        let activePortal = this._ionicApp._loadingPortal.getActive() ||
          this._ionicApp._modalPortal.getActive() ||
          this._ionicApp._toastPortal.getActive() ||
          this._ionicApp._overlayPortal.getActive();

        if (activePortal) {
          activePortal.dismiss();
          return;
        }

        // Navigate back
        if (this._app.getRootNav().canGoBack()) 
        this._app.getRootNav().pop();

      }
      else{
        // you are in the app
      };

  // Fake browser history on each view enter
  this._app.viewDidEnter.subscribe((app) => {
    history.pushState (null, null, "");
  });

Solution 2 Try to Add the these event listener in the platform ready:

 window.addEventListener('load', function() { window.history.pushState({}, '') 
           })
    window.addEventListener('popstate', function() { window.history.pushState({}, 
   '') })
Krsna Kishore
  • 8,233
  • 4
  • 32
  • 48
  • Is this code tested or you using it somewhere? I tried it but not working. Same problem persist. – Vivek Sinha Jan 23 '18 at 10:53
  • @VivekSinha havent tested , can you tell what case you tried? , update the question with the latest code what you have tried – Krsna Kishore Jan 23 '18 at 10:57
  • 1
    @V.Pivet can you explain that scenario? – Krsna Kishore Mar 29 '19 at 09:31
  • @Webruster . I'm on an Android device. I navigate in my app, I touch my back button 2 times. First time my back action is done, but second time my pwa is close. – V. Pivet Mar 29 '19 at 09:34
  • 1
    @V.Pivet try this one in platform ready `window.addEventListener('load', function() { window.history.pushState({}, '') }) window.addEventListener('popstate', function() { window.history.pushState({}, '') })` – Krsna Kishore Mar 29 '19 at 09:41
0

I have pretty much same requirement but none of the solution completely works, so i came up with my own. here i have used an array to keep track of visited page and removes it on back click event.

Note: window.onpopstate gets called even on pushing new page

import { Platform, Nav } from "ionic-angular";
import { HomePage } from "../pages/home/home";
@Component({
  templateUrl: "app.html"
})
export class MyApp {
  rootPage: any;
  @ViewChild(Nav) nav: Nav;
  pageHistory: string[] = [];//to track page history

  constructor(
    platform: Platform,
    statusBar: StatusBar,
    splashScreen: SplashScreen
  ) {

    window.addEventListener("load", function() {
    //adding a state to prevent app exit on back
      window.history.pushState({ noBackExitsApp: true }, "");
    });

    platform.ready().then(() => {
      window.onpopstate = evt => {
        let view = this.nav.getActive();
        if (this.pageHistory.find(x => x === view.name)) {
          if (!view.name.startsWith("Home")) {//handle a condition where you want to go back
            this.pageHistory = this.pageHistory.filter(n => n !== view.name);
            this.nav.pop().catch(reason => {
              console.log("Unable to pop :" + reason);
            });
          }
        } else {
          window.history.pushState({ noBackExitsApp: true }, "");
          this.pageHistory.push(view.name);
        }
      };

      this.rootPage = HomePage;
      statusBar.styleDefault();
      splashScreen.hide();
    });
  }
}
Fahadsk
  • 1,099
  • 10
  • 24