angularjs getting previous route path
Asked Answered
E

8

50
<h1>{{header}}</h1>
<!-- This Back button has multiple option -->
<!-- In home page it will show menu -->
<!-- In other views it will show back link -->
<a ng-href="{{back.url}}">{{back.text}}</a>
<div ng-view></div>

In my module config

  $routeProvider.
  when('/', {
    controller:HomeCtrl,
    templateUrl:'home.html'
  }).
  when('/menu', {
    controller:MenuCtrl,
    templateUrl:'menu.html'
  }).
  when('/items', {
    controller:ItemsCtrl,
    templateUrl:'items.html'
  }).
  otherwise({
    redirectto:'/'
  });

Controllers

function HomeCtrl($scope, $rootScope){
  $rootScope.header = "Home";
  $rootScope.back = {url:'#/menu', text:'Menu'};
}

function MenuCtrl($scope, $rootScope){
  $rootScope.header = "Menu";
  $rootScope.back = {url:'#/', text:'Back'};
}

function ItemsCtrl($scope, $rootScope){
  $rootScope.header = "Items";
  $rootScope.back = {url:'#/', text:'Back'};
}

As you can see in my controllers I have hard coded the back button url and text (Actually I don't need the text as using an image). In this way I found back button navigate incorrectly in some cases. I cannot use history.back() coz my back button changes to a menu link in home view.

So my question is how do I get the previous route path in controllers or is better way to achieve this ?

I have created a Plunker demonstration of my problem. Please check that.

Exacting answered 2/3, 2013 at 14:9 Comment(4)
Why do you need to manually handle back button navigation when AngularJS provides deep linking/back button functionality by default (example: wordcharconvertor.rogtopia.com)?Goldsberry
@stewie Sorry I'm newbie to angularjs and I didn't quite get what you mean. Could you please provide better example with better explanation? Please note my back link navigation's behavior is little different than browser's back buttonExacting
You should follow @MarkRajcok answer.Goldsberry
I was going to upvote this, but you didn't mark @andersh's answer.Pico
P
73

This alternative also provides a back function.

The template:

<a ng-click='back()'>Back</a>

The module:

myModule.run(function ($rootScope, $location) {

    var history = [];

    $rootScope.$on('$routeChangeSuccess', function() {
        history.push($location.$$path);
    });

    $rootScope.back = function () {
        var prevUrl = history.length > 1 ? history.splice(-2)[0] : "/";
        $location.path(prevUrl);
    };

});
Parkins answered 19/9, 2013 at 12:41 Comment(5)
Btw, I don' think you need to use $location, as the $routeChangeSucces callback is called with two parameters: current, next. docs.angularjs.org/api/ngRoute.$routeDissimilar
@KennethLynne I tried to use the current.$$route.originalPath instead of $location.$$path but the route parameters were only filled in when using $location. If you don't use route params then your suggestion should work.Pacifically
It should use with local storage for persistency. Otherwise history will be vanished if the page refreshed.Exacting
You are storing in rootscope , but when page refreshes(when user enters ctrl+ F5) it will disappear right?? So where to store that back function ????Disuse
Yes @sudhir, the history does not survive page refresh, if you need to persist it you should probably use local storage to store the history array.Parkins
M
22

Use the $locationChangeStart or $locationChangeSuccess events, 3rd parameter:

$scope.$on('$locationChangeStart',function(evt, absNewUrl, absOldUrl) {
   console.log('start', evt, absNewUrl, absOldUrl);
});
$scope.$on('$locationChangeSuccess',function(evt, absNewUrl, absOldUrl) {
   console.log('success', evt, absNewUrl, absOldUrl);
});
Magnetron answered 23/7, 2013 at 23:44 Comment(2)
Thanks @ArturBodera, I see they are now documented here: docs.angularjs.org/api/ng.$location#events I updated the answer.Magnetron
This saved my day... I had a problem of not reloading the controller, when one of the $routeParams changed due to user operating "back" and "forward" buttons in the browser. With these events I can catch this navigation.Admiral
A
19

In your html :

<a href="javascript:void(0);" ng-click="go_back()">Go Back</a>

On your main controller :

$scope.go_back = function() { 
  $window.history.back();
};

When user click on Go Back link the controller function is called and it will go back to previous route.

Alumna answered 21/4, 2016 at 7:9 Comment(2)
In my case, I did not need the $, I just used window.history.back();Achaean
@AppDevGuy $window is an angular wrapper for window, and you're encouraged to use it instead of window, because this way it can be mocked for testing etc. From angular docs (docs.angularjs.org/api/ng/service/$window): "In angular we always refer to it [to window] through the $window service, so it may be overridden, removed or mocked for testing."Jonejonell
P
5

@andresh For me locationChangeSuccess worked instead of routeChangeSuccess.

//Go back to the previous stage with this back() call
var history = [];
$rootScope.$on('$locationChangeSuccess', function() {
    history.push($location.$$path);
});

$rootScope.back = function () {
          var prevUrl = history.length > 1 ? history.splice(-2)[0] : "/";
          $location.path(prevUrl);
          history = []; //Delete history array after going back
      };
Presentiment answered 11/7, 2015 at 13:36 Comment(0)
G
4

This is how I currently store a reference to the previous path in the $rootScope:

run(['$rootScope', function($rootScope) {
        $rootScope.$on('$locationChangeStart', function() {
            $rootScope.previousPage = location.pathname;
        });
}]);
Gamboa answered 23/2, 2015 at 9:15 Comment(0)
P
4

You'll need to couple the event listener to $rootScope in Angular 1.x, but you should probably future proof your code a bit by not storing the value of the previous location on $rootScope. A better place to store the value would be a service:

var app = angular.module('myApp', [])
.service('locationHistoryService', function(){
    return {
        previousLocation: null,

        store: function(location){
            this.previousLocation = location;
        },

        get: function(){
            return this.previousLocation;
        }
})
.run(['$rootScope', 'locationHistoryService', function($location, locationHistoryService){
    $rootScope.$on('$locationChangeSuccess', function(e, newLocation, oldLocation){
        locationHistoryService.store(oldLocation);
    });
}]);
Perugia answered 3/11, 2015 at 16:59 Comment(1)
smart solution is the goal is save url globally, otherwise for single cases @MarkRajcok solution is a good wayAreaway
P
1

Just to document:

The callback argument previousRoute is having a property called $route which is much similar to the $route service. Unfortunately currentRoute argument, is not having much information about the current route.

To overcome this i have tried some thing like this.

$routeProvider.
   when('/', {
    controller:...,
    templateUrl:'...',
    routeName:"Home"
  }).
  when('/menu', {
    controller:...,
    templateUrl:'...',
    routeName:"Site Menu"
  })

Please note that in the above routes config a custom property called routeName is added.

app.run(function($rootScope, $route){
    //Bind the `$routeChangeSuccess` event on the rootScope, so that we dont need to 
    //bind in induvidual controllers.
    $rootScope.$on('$routeChangeSuccess', function(currentRoute, previousRoute) {
        //This will give the custom property that we have defined while configuring the routes.
        console.log($route.current.routeName)
    })
})
Protocol answered 6/3, 2013 at 5:34 Comment(1)
I'm getting the log in the console, but I still don't see how to go back in history. I think I've hit a bug in Angular with this issue: #17713235Beore
C
1

modification for the code above:

$scope.$on('$locationChangeStart',function(evt, absNewUrl, absOldUrl) {
   console.log('prev path: ' + absOldUrl.$$route.originalPath);
});
Cimabue answered 23/2, 2014 at 11:10 Comment(3)
That modification does not work if you are using route parameters. The parameters are not filled in for originalPathPacifically
$scope.on causes an error '$scope.on is not a function.' I think you use $scope.$on instead.Twodimensional
The param absOldUrl is the prev URL.Hild

© 2022 - 2024 — McMap. All rights reserved.