Order of lifecycle events

Is the current order of lifecycle events correct? It goes:

  1. beforeEnter new
  2. beforeLeave old
  3. afterEnter new
  4. afterLeave old

I would imagine something more like this:

  1. beforeLeave old
  2. afterLeave old
  3. beforeEnter new
  4. afterEnter new

The problem with the current lifecycle is that the history already changes at step one, before $ionicView.beforeLeave of the old view. If you have a delegate handler in your old view and want to access it before changing the view, you can’t (that I’m aware of).

See http://codepen.io/anon/pen/JdZXzW for the order (go to the about tab). The currentView changes immediately, even before leaving the home view. The scroll delegate is undefined before leaving the old view.

@mhartington or @perry, could you please weigh in on this? I can come up with a pull request if this is the wrong behavior.

1 Like

The entire lifecycle needs an overhaul in my opinion. The events don’t fire in the right order, history changes immediately before any events are fired, making canceling navigation needlessly difficult ($stateChangeStart doesn’t even cut it, fires too late) and much of the flow is simply confusing. Take $ionicNavView for example:

.controller('HomeCtrl', function($scope) {
    $scope.$on('$ionicNavView.beforeLeave', function() {
        console.log('before leave');
    });
});

You might think this executes before you leave the HomeCtrl view, but it actually executes when entering HomeCtrl. The “before leave” part is before you leave another view, but executed in the scope of the new view. Only the history has already changed, so “before” is actually “after”.

@mhartington I know everyone is busy with turning Ionic into a viable business model, but I hope you guys can find some time to dive into this topic. Pull requests, even the low hanging fruit, have largely been ignored for the past few months, so I hope Ionic gets some love again soon.

No point in overhauling these events, they work just as intended.

This is the order of events during the first view initialization:

View 1 - loaded
View 1 - beforeEnter
View 1 - enter
View 1 - afterEnter

This is the order of event during the view transition:

View 2 – loaded
View 2 – beforeEnter
View 1 – beforeLeave
View 2 – enter
View 1 – leave
View 2 – afterEnter
View 1 – afterLeave

You can play with a working example here: http://www.gajotres.net/understanding-ionic-view-lifecycle/

4 Likes

Hi @Gajotres, I know what the order is (also mentioned in my first post and demo), and I know how it should work in theory. However the theory doesn’t match the practice. We can argue about the order – I think it should be beforeLeave -> beforeEnter – but I’d be okay with the current behavior if it worked as advertised.

Your blog post (and the documentation) claims that beforeLeave is triggered “when the view is about to leave and no longer be the active view”. So it is still the active view, right? Well no, that’s not what happens.
Take this example: http://codepen.io/anon/pen/NqBQJd

Click on the About tab. You’ll see an alert box with three different ways of trying to detect the active view. According to $ionicHistory, it’s already changed to tabs.about (beforeLeave!!) so that’s wrong. According to ion-view[nav-view=“active”], it’s still home (correct). And according to ion-nav-view[nav-view=“active”] it’s the about tab (also wrong if we follow the docs).
Now here’s where it becomes interesting. Click on home and about again. You’ll notice that when the about tab is cached, ion-nav-view active all of a sudden does become home. So the first time it’s wrong, the second time it’s correct.

Here’s another example of where it goes wrong, this time trying to cancel changing states. If beforeLeave worked correctly, and the active view would still be the one you’re about to leave, you could expect to easily cancel that process. Here’s an example, trying to cancel going to the about that from beforeLeave: http://codepen.io/anon/pen/pJOzNV

Well that did nothing (this bug has been reported). Okay, let’s try another way, using $stateChangeStart: http://codepen.io/anon/pen/OVoLWp
This did something. The about tab content does not get loaded, but about still becomes the active tab. This is the same discrepancy we saw before. Ion-view cancels correctly and keeps home as active, but ion-nav-view ignores this and changes the tab anyway. Again this would work differently if about was already cached. In that case, both home and about would be active.

Finally if you look at the actual code, you can see that in order to switch to a different view, you first need to register that view in history. Once you do that, the active view changes. Only afterwards do you start emitting leave events. If you want to do any cleanup that relies on the active view (like delegate handlers), or cancel changing views, you’re already too late.
As you can see from my examples, it’s not just one thing. It works fine on the surface, but if you try anything slightly more complex, there are simply too many edge cases, discrepancies between Ionic and AngularUI Router, and downright bugs. This is why I’m advocating for a second look at this functionality.

@fjansen Respect, this is worthy reply

Give me some time to go through all these examples.

So is there any known possibility at the moment to cancel navigation? e.g. for showing a user a modal if he really wants to navigate away

Not if you’re using Ionic’s nav view, at least to my knowledge. There might be some hacked workaround, but it wasn’t immediately clear to me what that would be. Most likely related to $stateChangeStart, since that at least does something. It stops the new view from loading, though it still becomes the active one. So maybe you could reset the active view manually, not sure.

@Gajotres Wondering if you had any updates on this?

Unfortunately no, I’m away from forum lčast few days, I’ve been working on a big project. I’ll get to it when I come back. It’s in my TODO.