I did a small experiment: http://codepen.io/hawkphil/pen/NqMomm?editors=101
Here is my state flow (click on the buttons): Home -> Fact1 -> Fact2 -> Fa
There are a lot of questions about history and navigation among the issues open on github.
I guess the navigation is broken and needs to be fixed.
$ionicHistory
keeps track of the view pushing each visited view on a stack.
Actually there are 2 arrays there:
$ionicHistory.viewHistory().views
and
$ionicHistory.viewHistory().histories
I guess the first one is the history of views for the current stack while the second considers all the histories.
Different navigations can have different histories: tabs, sidemenu etc etc, and Ionic should remember each state when you switch from one history to the other.
Reading through their documentation you can find this:
Unlike a traditional browser environment, apps and webapps have parallel independent histories, such as with tabs. Should a user navigate few pages deep on one tab, and then switch to a new tab and back, the back button relates not to the previous tab, but to the previous pages visited within that tab.
You can find the currentHistoryId here: $ionicHistory.currentHistoryId()
.
I've changed your example a little bit displaying the 2 arrays when entering the view of the main controller:
.controller('MainCtrl', function($scope, $rootScope, $timeout, $ionicHistory) {
$scope.$on('$ionicView.enter', function(e) {
var history = $ionicHistory.viewHistory();
angular.forEach(history.views, function(view, index){
console.log('views: ' + view.stateName);
});
angular.forEach(history.histories[$ionicHistory.currentHistoryId()].stack, function(view, index){
console.log('history stack:' + view.stateName);
});
});
})
As you can see, the first array views keeps track of all the views you have visited.
If you go back and forth in doesn't add elements if you are displaying a view you've previously visited.
Each view has two properties: backViewId and forwardViewId. These 2 values seems to be part of the view when the elements are added to the collection. They don't change when you navigate.
So, what happens is when you follow the sequence:
Home -> Fact1 -> Fact2 -> Fact3 -> Fact2
Ionic finds the view Fact2
in the collection, gets it's backViewId
(which points to Fact1
) and that's what it will use as a view to go back to.
I didn't some debugging in the code and tried to force the back-view myself but things get messed up.
I guess they've chosen this path cause when you're back to the root - home - the back button should be hidden. Things don't work as expected when you follow the sequence:
Another thing I've noticed is the fact that sometimes views are added to this collection even if the element is already there.
You can try the sequence:
Home -> Fact1 -> Fact2 - Home (button)
As you can see now the back button (in the header) tells you the back view is Fact2 and in fact the console shows the same:
For some strange reason this time a new view has been added to the collection and the regular pattern has changed.
There's a codepen here with some tests.
My solution/workaround:
Create an additional state to traverse to that references the same url, templateUrl, and controller.
For example if I have:
$stateProvider.state('fact2', {
url: '/fact2/:factFilter',
templateUrl: 'fact2.html',
controller: 'Fact2Ctrl'
})
Then I also create a "fact2" duplicate with only a different state name
$stateProvider.state('fact2_duplicate', {
url: '/fact2/:factFilter',
templateUrl: 'fact2.html',
controller: 'Fact2Ctrl'
})
If I am receiving the funny transition behavior, I can call $state.go('fact2_duplicate')
and the history will be more inline to what I am expecting.
Hope this helps someone.