4
votes

I'm having a hard time understanding how the Ember router calls hooks on nested resources during link-to transitions. There are no dynamic segments involved in this example.

Here's a contrived example that mimics my app:

App.Router.map(function() {
  //Modal resources
  this.resource('modal', function(){

    this.resource('posts', function(){
      this.route('new');
      this.route('edit')
    });

    this.resource('photos', function(){
      this.route('new');
      this.route('edit');
    });
})

On a FULL PAGE RELOAD of the posts route, let's say, we see that the beforeModel and afterModel hooks on Application > Index > Modal routes are fired in sequence. Good, makes sense.

Attempting URL transition to /modal/posts ember.js?body=1:3912
Transition #0: application: calling beforeModel hook ember.js?body=1:3912
Transition #0: application: calling deserialize hook ember.js?body=1:3912
Transition #0: application: calling afterModel hook ember.js?body=1:3912
Transition #0: modal: calling beforeModel hook ember.js?body=1:3912
Transition #0: modal: calling deserialize hook ember.js?body=1:3912
Transition #0: modal: calling afterModel hook ember.js?body=1:3912
Transition #0: posts: calling beforeModel hook ember.js?body=1:3912
Transition #0: posts: calling deserialize hook ember.js?body=1:3912
Transition #0: posts: calling afterModel hook ember.js?body=1:3912
Transitioned into 'posts' ember.js?body=1:3912
Transition #0: TRANSITION COMPLETE. 

However, when I click

{{link-to 'Go to Photos' 'photos'}}

in EITHER the modal.hbs template or the posts.hbs template, it doesn't cascade through the Application > Index > Modal hook sequence. It only hits the very-most child leaf hooks:

Attempting transition to photos ember.js?body=1:3912
Transition #1: photos: calling beforeModel hook ember.js?body=1:3912
Transition #1: photos: calling deserialize hook ember.js?body=1:3912
Transition #1: photos: calling afterModel hook ember.js?body=1:3912
Transition #1: Resolved all models on destination route; finalizing transition. 
Transitioned into 'photos' ember.js?body=1:3912
Transition #1: TRANSITION COMPLETE. 

Could some kind soul clear up how the router is supposed to work, especially on link-to transitions? I want all parent routes' beforeModel/afterModel hooks to be hit in sequence. From what I've researched (a lot), Ember is supposed to hit all the parent route beforeModel/afterModel hooks, top-down, on every transition.


Edit specifically for kingpin2K's response: Ok that makes sense, but

App.Modal = Ember.Route.extend({

  model: function(params){
    //load some data that you want modal.photos to also have access to
    console.log('Modal route model hit')
  },

  afterModel: function(model) {
    this.transitionTo('modal.photos')
  }
});

calls the Modal parent route twice when navigating to it. 1) on the direct hit to Modal url, and 2) again on the afterModel redirect (transitionTo modal.photos). Under your explanation, the Modal parent route hooks (especially the model hook!) wouldn't fire on the subsequent transition from modal (parent) to modal.photos (child), but they are. You will get two console logs when you go to the parent 'modal' route.

Thanks again for your help.

1
Superb question, exactly what I wanted to work out. I'm commenting, rather than answering, as I still don't know for user - but it would seem to me that if you're just changing between 'photos.new' and 'photos.edit', the parent 'photos' route is not actually meant to be called, as the aspects of that route (like a parent template, say) are not being reloaded. Looks like a feature to me. - Mick Byrne

1 Answers

2
votes

It's easiest to think of the router as a stack, with each resource/route an item in the stack. As you move from resource to resource it pops irrelevant items from the stack, then pushes new relevant items that aren't yet fetched.

A parent resource shouldn't be dependent on the child resource, or it wouldn't really be a parent resource. With this paradigm in mind, it would be pointless to refetch parent models when transitioning to a new resource/route in the router.