Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Ionic 4/Angular loops in router history

If I navigate from one page to another and back multiple times , I am able to navigate through the whole router history via the hardware- or the browser back button.

I want to achieve that the hardware back button brings me to the same page as the ion-back-button in my toolbar.

Example

Page 1 > Page 2 > Page 3

I navigate from Page 1 to Page 2. Then I navigate from Page 2 to Page 3 and back via ion-back-button multiple times. If I then press the hardware/browser back button, I get to Page 2 and Page 3 again in a loop. Instead I want the hardware/browser back button to navigate to Page 1 if I press it on Page 2.

like image 979
matthiasunt Avatar asked Jan 22 '19 10:01

matthiasunt


1 Answers

Here is how I fixed the router looping problem on Ionic 4. I am aware and previously implemented the famous back button workaround in Ionic 3, but that won't work on Ionic 4 since it uses angular routing.

So I was looking for some way to get the currently active view instance. If I get the view instance, then I can call some backButtonAction function defined on that page (similar to the Ionic 3 workaround).

Okay, enough chit-chat. here is the code:

app.component.ts

export class AppComponent {
    @ViewChildren(IonRouterOutlet) routerOutlets:QueryList<IonRouterOutlet>;
    constructor(
    private alertCtrl:AlertController,
    private modalCtrl:ModalController,
    private actionSheetCtrl: ActionSheetController,
    private menu:MenuController,
    private platform: Platform
    ){
        this.initializeApp(); 
    }

    initializeApp(){
        ...
        this.registerHardwareBackButton();  
    }

    registerHardwareBackButton() {
        this.platform.backButton.subscribe((e) => {
            e.register(999, async () => {   
            // first close any alets, modal etc. 

            const actionsheet = await this.actionSheetCtrl.getTop();             
            if(actionsheet){
                actionsheet.dismiss();
                return;             
            }

            const modal = await this.modalCtrl.getTop(); 
            if(modal){
                modal.dismiss();
                return;
            }

            const alert = await this.alertCtrl.getTop();            
            if(alert){
                alert.dismiss();
                return;             
            }

            const menu = await this.menu.getOpen();
            if(menu){
                menu.close();
                return; 
             }

             const outlet:any = this.routerOutlets.first();
             const activeView = outlet.activated.instance; // the active view instance          
             //now calls the onBackButtonPress function in that instance            
             if(activeView.onBackButtonPress){
                activeView.onBackButtonPress();                 
             }else {
                //some logic about what to do if onBackButtonPress is not defined, default action       
             }
          });
       }); 
    }

and if you have a user navigation flow like this HomePage => Page1 => Page2 define onBackButtonPress function on each like (just like the workaround for Ionic 3).

example: on HomePage

onBackButtonPress(){
    navigator['app'].exitApp(); //closes the app, bad UX
}

on Page1

onBackButtonPress(){
    //back to previous page using location.back() or nav.pop()
    this.location.back();
}
like image 140
HasilT Avatar answered Oct 14 '22 02:10

HasilT