waXve
waXve

Reputation: 862

Change location of browser's back button in angular js

I have a wizard with multiple Steps. Let's say something like this:

Product > Address > Payment > Verify

On the /verify step, the user buys something. If the user now presses the back button on the browser, he should go to the /product step and not to the /payment step. To do so, I want to change the browser history from /payment to /product so that he can buy more stuff.

I use angularjs 1.3.14 with enabled HTML5 mode and ui-router 0.2.10. So the solution might use HTML5 history. but it would be nice if it also works for older browsers. But the support is nice to have.

Upvotes: 1

Views: 1912

Answers (4)

Awatatah
Awatatah

Reputation: 474

I know this is old but to help others, what I do is call .replace() before I call .path() to set the location of the back button. So in your case I would do:

// some code in Payment controller...

// call .replace() to set the history to '/product'
$location.replace('/product');
// now change .path()
$location.path('/verify');

Now on the /verify route, if the user presses the browser's back button, it should take them to /product route instead of /payment.

One thing to mention is I that I do not know if this will work on older browsers but I can confirm it works in Chrome 66.0.3359.181 and Safari 11.1

Reference: Location.replace()

Upvotes: 0

waXve
waXve

Reputation: 862

The answer from stackg91 gives me the right idea. As I don't want to change the page to rechange it in the next moment, I listen on $stateChangeStart. So I've done something like this (pseudocode)

 obj.finishedStateListener = $rootScope.$on('$stateChangeStart', function (event, toState) {
     if(statechange inside wizard) {
         event.preventDefault();
         obj.finishedStateListener();
         $state.go(initState);
     }
 })

It is very important to save the return of the $on function, as it gives you the possiblility to unregister the eventListener. If you forget to call it, you will end in an infinite loop.

Upvotes: 0

areim
areim

Reputation: 3741

In HTML5 you can manipulate with history object: https://developer.mozilla.org/en-US/docs/Web/Guide/API/DOM/Manipulating_the_browser_history

Actually, you can modify only the last entry, with two options:

  • pushState() - add a new state at the end of history
  • replateState() - change the last entry with new one

It is supported quite well http://caniuse.com/#feat=history, but be careful with older IE.

Don't forget to use fallback as:

if (history.pushState) {
    // your code with history manipulation
} else {
    // your fallback code for older IE and others
}

Upvotes: 0

stackg91
stackg91

Reputation: 594

Ok so basicly you could use States for this

.config(function($stateProvider, $urlRouterProvider) {
$stateProvider

  // setup an abstract state for the tabs directive
    .state('product', {
    url: "/product",
    templateUrl: "templates/product.html",
    controller: "productCtrl"
  })

   .state('Address', {
    url: "/Address",
    templateUrl: "templates/Address.html",
    controller: "AddressCtrl"
  })

   .state('Payment', {
    url: "/Payment",
    templateUrl: "templates/Payment.html",
    controller: "PaymentCtrl"
  })

   .state('Verify', {
    url: "/Verify",
    templateUrl: "templates/Verify.html",
    controller: "VerifyCtrl"
  })

});

In your Main Controller you can watch for Statechanges

$rootScope.$on('$stateChangeSuccess', function (ev, to, toParams, from, fromParams) {
    if(from.name == 'verify' && to.name == 'payment'){
    $state.go('product')
    redirect example
     }

});

dont forget to inject $state!

Upvotes: 1

Related Questions