2

I have a MainCtrl containing a backstack for history, like this;

$scope.urlHistory = [];

$scope.$on('$routeChangeSuccess', function () {
    if ($location.$$absUrl.split('#')[1] !== $scope.urlHistory[$scope.urlHistory.length - 1]) {
        $scope.urlHistory.push($location.$$absUrl.split('#')[1]);
    }
});

Then, in the same controller I've got a GoBack() function I'd like to call when the back button is pressed;

$scope.goBack = function () {
    $scope.urlHistory.pop();
    $location.path($scope.urlHistory[$scope.urlHistory.length - 1]);
};

This is supposed to work because from my index.html I call it with ng-click="goBack()" and everything works as expected.

I use this for the device events, same controller;

function onBackKeyDown() {
  alert("back");
  $scope.goBack();
}

document.addEventListener("deviceready", onDeviceReady, false);
// device APIs are available
//
function onDeviceReady() {
  // Register the event listener
  alert("deviceready");
  document.addEventListener("backbutton", onBackKeyDown, false);
};

I can see the alerts, but the app's not navigating back. Something happens though, because if I press the device back button twice, the ng-click="goBack()" suddenly takes me back to the start page of the app. Am I using $scope wrong? Experiencing this on Win Phone & Android. Using Phonegap Build.

edit: What I'm really after here is why would my $scope.goBack(); function work differently when called from the devicelistener.

Johan Baaij
  • 584
  • 1
  • 5
  • 15
  • What is the overall purpose of this code? Is it just to navigate to the previous page when the user clicks the back button? – tennisgent Apr 10 '14 at 19:06
  • Sorry if that was unclear, that's exactly what the purpose is indeed. – Johan Baaij Apr 10 '14 at 19:32
  • I know a bit better what is going wrong. $location.path(); does not work when invoked by the event listener. Calling it with ng-click works fine. – Johan Baaij Apr 21 '14 at 12:49

2 Answers2

1

This solved it:

  $scope.goBack = function () {
    if (urlHistory == '/') { 
      document.removeEventListener("backbutton", onBackKey, false);

    };    
    urlHistory.pop();
    $location.path(urlHistory[urlHistory.length - 1]);
    $scope.$apply();
  };

The scope.$apply(); was my answer. It's necessary when executing angular expressions outside of angular. (AngularJS $location not changing the path)

Community
  • 1
  • 1
Johan Baaij
  • 584
  • 1
  • 5
  • 15
0

You should be able to just use the browser's built-in history object for this. For example:

function onDeviceReady() {
    document.addEventListener("backbutton", function () {
        window.history.go(-1);
    });
}

You shouldn't need to do anything specific just because you're using angular. Unless I'm missing something else...

UPDATE: After looking at the phonegap docs, it looks like the default backbutton behavior already does what you want... or are you trying to do something special?

tennisgent
  • 14,165
  • 9
  • 50
  • 48
  • You're right, except the default back button behaviour for Windows Phone (8) seems to be exiting the app. That's why I'm using my own "history object". Also, window.history.go(-1) does not work on Windows Phone. – Johan Baaij Apr 11 '14 at 07:33
  • Ok, sorry. Whenever I've done phonegap development I've only ever targeted iOS and Android so I'm not familiar with windows phone quirks. But the principle should be the same. Whatever cross-platform code that will go back in the browser's history should go in the `"backbutton"` listener. See [this post](http://stackoverflow.com/questions/3588315/how-to-check-if-the-user-can-go-back-in-browser-history-or-not) for more info. – tennisgent Apr 14 '14 at 13:08