Ember.js: Nested routes can't find top level loading substates

Created on 18 Sep 2015  Â·  11Comments  Â·  Source: emberjs/ember.js

According to the loading substate guide, if I define an app/templates/loading.hbs, any slow loading route should be able to find it. However, this is not happening with nested routes. Nested routes seem to only look as far as the route that initiated the transition.

Consider the example of three routes, each of which contains an asynchronous model hook:

  • foo
  • foo/bar (or in router terms, foo.bar)
  • foo/bar/baz (or, foo.bar.baz)

Transitioning from index to foo triggers the loading substate.
Transitioning from index to foo.bar triggers loading.
Transitioning from index to foo.bar.baz triggers loading.
Transitioning from foo to foo.bar does not trigger loading
Transitioning from foo to foo.bar.baz does not trigger loading
Transitioning from foo.bar to foo.bar.baz does not trigger loading

Enabling resolver logging shows that the search for a loading substate stops at the source route. For example, going from foo to foo.bar stops the search at foo/loading; going from foo.bar to foo.bar.baz stops the search at foo/bar/loading. Based on the substate guide, I would expect the entire route hierarchy to be traversed until the top level loading template is found (because otherwise you would need to put loading templates at just about every level of your route hierarchy).

Most helpful comment

@mike-post I created an ember-twiddle example here: http://ember-twiddle.com/d6bf04c4df3a65f8f26d (twiddle uses pods by default)

My question is: does the code have a bug or is the guide wrong/misleading?

I think that perhaps the guides are not completely clear regarding the use of a loading template.

This is not a bug.

In the guides…

Ember will try to find a loading route in the hierarchy above foo.bar.slow-model that it can transition into, starting with foo.bar.slow-models's sibling:
foo.bar.loading
foo.loading
loading

…notice the wording around sibling and think about the routing transitions.

In the ember-twiddle example ^ the foo/loading/template.hbs file is utilized when transitioning from:

application/index -> foo/bar
application/index -> foo/bar/baz
foo -> foo/bar
foo -> foo/bar/baz

But the foo/loading/template.hbs file is NOT utilized when transitioning from:

foo/bar -> foo/bar/baz

Hence the need to put the loading template at the level in the routing that the transitions begin, which is basically everywhere as in this ember-twiddle example - http://ember-twiddle.com/f36ddad0ddc88449c968

I believe it would be a feature request to resolve a path to a loading template anywhere between the transition start and end. Perhaps write up an RFC issue, see the feature request docs - https://github.com/emberjs/ember.js/blob/master/CONTRIBUTING.md#requesting-a-feature

All 11 comments

because otherwise you would need to put loading templates at just about every level of your route hierarchy

You do.

But you shouldn't have to. According to the routing substate guide ember should traverse to the base of the application's route hierarchy:

Ember will try to find a loading route in the hierarchy above foo.bar.slow-model that it can transition into, starting with foo.bar.slow-models's sibling:

  1. foo.bar.loading
  2. foo.loading
  3. loading

Considering also the loading event, the routing substate guide states:

If the loading handler is not defined at the specific route, the event will continue to bubble above a transition's parent route, providing the route:application the opportunity to manage it.

This seems to imply that the loading event specifically bubbles up the entire route hierarchy from the target route up to route:application. It is not unreasonable to assume that the resolver will perform the same resolution path when looking for a loading route into which it can perform an intermediate transition. However, that is clearly not happening and is demonstrated by the resolver logging in the sample code provided.

The routing guide and the code are clearly in disagreement. As a consumer of the framework who applies common sense, it seems that the intent of the guide is correct and this is an error in the code.

because otherwise you would need to put loading templates at just about every level of your route hierarchy

You do.

This is what I don't understand. It seems like a poor design constraint from ember if I need to copy/paste my loading screen into every route (even if that loading screen is effectively just a component). Why can't I just define a loading screen at the root of my hierarchy and be done with it? It seems like the resolver should be able to do the heavy lifting for me. And the guides seem to indicate that it should be so. Hence ... bug.

:+1: Agreeing with you @mike-post! I'm experiencing this unexpected behaviour (at least according to the guides) as well.

I did a small JSFiddle to illustrate this matter as well: http://jsfiddle.net/rkjaer/wctu9m0v/

@mike-post if the guides are not correct that is an issue with the guides repo @locks can fix that.

And the guides seem to indicate that it should be so

However Your expectation from the guides may not be correct. Your repo with the example only has a loading template at the top route. so only a transition beginning from that route has a loading template.

A transition beginning from a route without a loading template doesn't have the behavior of rendering a loading template.

In the guides:

Ember will try to find a loading route in the hierarchy above foo.bar.slow-model that it can transition into, starting with foo.bar.slow-models's sibling

…May seem to indicate that one loading template at the top of the route tree (route > child > grandchild) would work. But that is not what it says. It says it will try to find a loading route (not a loading template). it also doesn't say that it will generate a loading route for any route with a loading template (which I don't even know how the magic happens).

Based on your example if you want a transition from any route in the tree you will need to provide a loading template at that level.

A transition beginning from a route without a loading template doesn't have the behavior of rendering a loading template.

I agree that's the current behavior. My question is: does the code have a bug or is the guide wrong/misleading? I'd posit that the sensible thing to do is to define a single top level loading template which can be used by the entire application thus the bug would be in the code. Based on slack conversations, I am far from the only one possesses this point of view. (This bug exists because the consensus in the #needhelp channel was that the current behavior was broken and a bug should be filed.)

It says it will try to find a loading route (not a loading template). it also doesn't say that it will generate a loading route for any route with a loading template (which I don't even know how the magic happens).

That's a good point. I've updated the example repo to include an explicit loading route. The result is unchanged.

@mike-post I created an ember-twiddle example here: http://ember-twiddle.com/d6bf04c4df3a65f8f26d (twiddle uses pods by default)

My question is: does the code have a bug or is the guide wrong/misleading?

I think that perhaps the guides are not completely clear regarding the use of a loading template.

This is not a bug.

In the guides…

Ember will try to find a loading route in the hierarchy above foo.bar.slow-model that it can transition into, starting with foo.bar.slow-models's sibling:
foo.bar.loading
foo.loading
loading

…notice the wording around sibling and think about the routing transitions.

In the ember-twiddle example ^ the foo/loading/template.hbs file is utilized when transitioning from:

application/index -> foo/bar
application/index -> foo/bar/baz
foo -> foo/bar
foo -> foo/bar/baz

But the foo/loading/template.hbs file is NOT utilized when transitioning from:

foo/bar -> foo/bar/baz

Hence the need to put the loading template at the level in the routing that the transitions begin, which is basically everywhere as in this ember-twiddle example - http://ember-twiddle.com/f36ddad0ddc88449c968

I believe it would be a feature request to resolve a path to a loading template anywhere between the transition start and end. Perhaps write up an RFC issue, see the feature request docs - https://github.com/emberjs/ember.js/blob/master/CONTRIBUTING.md#requesting-a-feature

@locks perhaps some clarity is needed in the Guides regarding loading templates, see the example twiddle links:

Yes, this is really confusing. I was also expecting the global loading to be used for nested routes.

Another thing. Let's say I override the loading event (in my case, in a Mixin in order to have a shared loading substate template between subroutes of different routes) . Any idea on howto override the rendered template?
I tried this.render or transition.router.intermediateTransitionTo but with no luck...

As this seems to be a documentation issue, will close this now. If we need to clarify docs further, please open an issue in the guides repo and reference this issue. Thanks!

Was this page helpful?
0 / 5 - 0 ratings