Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[v4.0.0-beta.12] When platform hardware backButton subscribed, router.goBack should not be triggered #15820

Closed
peterpeterparker opened this issue Oct 1, 2018 · 13 comments
Assignees
Labels

Comments

@peterpeterparker
Copy link
Contributor

peterpeterparker commented Oct 1, 2018

Feature Request

Ionic Info

Ionic Angular v4.0.0-beta.12

Describe the Feature Request
In my app, I've got many pages where the back action is overridden. For example, I've got a wizard build on top of ion-slides. There, when the user click "back", he/she don't necessarily want to go back in the navigation but rather want to go back the previous slide

In Ionic v3 registerBackButtonAction allowed me to override the hardware back button. When I was doing so, no extra back action where triggered

In Ionic v4 backButton allows me to override the hardware back button, but doing so, an extra back action is automatically triggered (see the @Listen('document:ionBackButton') in https://github.com/ionic-team/ionic/blob/7d50305b7f6c48392dd278b55824e4c712890214/core/src/components/router/router.tsx and win.document.dispatchEvent(ev); in https://github.com/ionic-team/ionic/blob/c49d896e085278a4ece521a22d983a4fa745adc2/core/src/utils/hardware-back-button.ts)

Summarized of the behavior:

Ionic v3 = Subscribe to back button = custom code/back is executed
Ionic v4 = Subscribe to back button = custom code/back is executed + general back executed too

Describe Preferred Solution
I see two solutions:

  1. hardware-back-button.ts should not trigger anymore the event ionBackButton letting users implement their own navigation

  2. a new feature or option should be implemented in order to specify, while subscribing to the hardware back button, that the automatic back navigation should not be triggered

Describe Alternatives
Don't know maybe there are other solutions workarounds? What I could say is that it's a core need for my app in order to be able to unleash my app on Android

Related Code

Ionic v3

     this.unregisterCustomBackActionFunction = this.platform.registerBackButtonAction(() => {
            if (this.something) {
                this.slider.slidePrev();
            } else {
                this.navController.pop();
            }
        });

Ionic v4

  this.customBackActionSubscription = this.platform.backButton.subscribe(async ($event) => {
          if (this.something) {
             await this.slider.slidePrev();
         else {
             await this.navCtrl.navigateBack('/somewhere');
    });

Additional Context
There is a discussion started on the Ionic Forum: https://forum.ionicframework.com/t/ionic-4-prevent-backbutton-from-closing-page

A bit ugly workaround
I need this option because my page contains a slider and I want to navigate back with the hardware back button to the previous slide. The trick which seems to work, is to add state in the history, therefore, the automatic back action (see goBack or the ion-router https://github.com/ionic-team/ionic/blob/7d50305b7f6c48392dd278b55824e4c712890214/core/src/components/router/router.tsx) will go back in the navigation history by first popping the states I added

Like

<ion-slides (ionSlideNextEnd)="pushHistoryState()">

async pushHistoryState() {
        const sliderIndex: number = await this.slider.getActiveIndex();
        history.pushState({newAd: sliderIndex}, document.title);
    }
}

also of course you should do the same for the action which would slide to previous slide by poping the state

history.back(1);

Update

Just noticed another use case where having an automatic navigation is not well suited: in case for example you would close a modal with in any case a value. With an automatic navigation executed with the hardware back button, the modal just gonna always be dismissed with no values. So far I noticed 8 modals in my app which are impacted by this

@ionitron-bot ionitron-bot bot added the triage label Oct 1, 2018
@RHinderiks
Copy link

Personally i wish we could override the back button per button since we already have to put them manually in there. Adding [backAction]="customFunction()" or something similar would be great. This function should also be triggered when using the hardware button (or even an option to disable the hardware button but this probably isn't a great idea ?)

@peterpeterparker
Copy link
Contributor Author

awesome, thx @manucorporat ❤️

@RHinderiks
Copy link

With this fix, Whats the best practise to go about implementing custom back button functionality now ?

@peterpeterparker
Copy link
Contributor Author

peterpeterparker commented Oct 2, 2018

@RHinderiks here you go for v4-beta.12, credit @manucorporat too:

@HostListener('document:ionBackButton', ['$event'])
private overrideHardwareBackAction($event: any) {
    $event.detail.register(100, async () => {
          // Do what you want
    });
}

@peterpeterparker
Copy link
Contributor Author

@RHinderiks I've updated my previous answer, furthermore to the listener, the $event.detail.register is important

@bergben
Copy link

bergben commented Oct 14, 2018

How about in v4-beta.13 which includes 6a5aec8 ?

@mateusduraes
Copy link

There is a way to register a custom function to hardware back button and stop the default event / propagation?
I have the following scenario, i have a modal that i need to call a function and dismiss with some data, when i touch the hardware back button, the function, obviously, are not being called. I need to call this function but i need also to prevent the default event.

private handleHardwareBackButton(): void {
    const sub = this.platform.backButton.subscribe((event: Event) => {
      event.stopImmediatePropagation();
      event.stopPropagation();
      event.preventDefault();
      this.dismiss();
    });
    this.subscriptions.push(sub);
  }

  ngOnInit() {
    this.handleHardwareBackButton();
  }

  ngOnDestroy() {
    unsubscribeSubscriptions(this.subscriptions);
  }

The function is called, but the event is not stopped.

@peterpeterparker
Copy link
Contributor Author

you could use subscribeWithPriority see above commit linked with this issue release in beta.13

@peterpeterparker
Copy link
Contributor Author

or HostListener as described in my example above

@mateusduraes
Copy link

@peterpeterparker Thanks, the following code works for me.

 private handleHardwareBackButton(): void {
    const sub = this.platform.backButton.subscribeWithPriority(9999, () => {
      console.log('called');
      this.dismiss();
    });
    this.subscriptions.push(sub);
  }

  ngOnInit() {
    this.getStates(this.payload);
    this.handleHardwareBackButton();
  }

  ngOnDestroy() {
    unsubscribeSubscriptions(this.subscriptions);
  }

I used 9999 as the priority because it doesn't work with 1. I don't know witch is the highest priority inside the framework.

@StarDee
Copy link

StarDee commented Nov 12, 2018

@RHinderiks here you go for v4-beta.12, credit @manucorporat too:

@HostListener('document:ionBackButton', ['$event'])
private overrideHardwareBackAction($event: any) {
    $event.detail.register(100, async () => {
          // Do what you want
    });
}

It's useful in the App,but what should I use on the web ?

@RHinderiks
Copy link

Is there also a way to override the function on a regular ion-back-button inside a ion-toolbar ? Right now you can give it a href but i would like to show a confirmation dialog first

@ionitron-bot
Copy link

ionitron-bot bot commented Jan 9, 2019

Thanks for the issue! This issue is being locked to prevent comments that are not relevant to the original issue. If this is still an issue with the latest version of Ionic, please create a new issue and ensure the template is fully filled out.

@ionitron-bot ionitron-bot bot locked and limited conversation to collaborators Jan 9, 2019
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
Projects
None yet
Development

No branches or pull requests

6 participants