Proposal: Nested Loading Routes

We definitely don’t facilitate that pattern as the default; i think angular ui-router does let you do that, but lots of people run into the problem of child route’s promises depending on the resolved values of parent route promises, so that’s not the default in Ember.

I hacked this together, i’m sure there’s a better way, but here’s one approach: http://jsbin.com/ucanam/1741/edit

Do you recall when has this change been made? I’m not sure if I remember correctly, but I think that 1.0 RCs where still running model hooks concurrently and the rest of the things was paused (setup controllers, rendering).

I agree that some people may expect that a model hook of a child route should have access to parent’s model data, but I have megadoubts on having to do any hacks to achieve this (btw. if you agree that we should have a better API for this, I’m would love to work on this, maybe I will finally start contributing to the framework).

The reason why I’m saying this is of course performance. I’m willing to have a potentially slower boot time to get all the good things associated with loading and error callbacks, but I usually don’t care about the synchronous loading of models. Especially when the list does not contain all the information needed for detailed view and there needs to be a request done for an individual item.

Do you think we could add some kind of API to immediately start fetching child model hook? Maybe some attribute on the promise object or a flag on a route itself?

And the last thing - in the gist you provided you use articles_loading route. When I change articles_loading to articles/loading, I can see the loading route, but after articles finish loading, the articles template is not loaded in place of the loading template, why is that happening?

RC6 was when the async router facelift landed, which unified transition semantics between URL changes and transitionTo/linkTo; before RC6, URL transitions would sequentially pause for promises whereas transitionTo would not, which might be what you’re thinking of, but since RC6, nothing has been added/changed to affect the way route hierarchy model hooks sequentially resolve.

It seems that the likely-to-be-adopted solution is to add something like Ember.resolveQuickly that can wrap thennables returned from Ember Data’s .find in a proxy that doesn’t have a .then property. Maybe Ember Data model objects / record arrays would get a .resolveQuickly() shorthand method. This would give more control over the transition behavior. Alternatively we could have some flag on the route, resolveQuickly: true, etc.

The weird behavior with loading states that you’re seeing stems from the fact that because we don’t return a thennable from ArticlesRoute, it considers that route’s model resolved, so when you change it to articles/loading, it will enter ArticlesRoute, call its setupController before my the promise has resolved, so the articles property is still blank. If ArticlesRoute had returned a record array (perhaps wrapped in resolveQuickly), this wouldn’t be a problem.

Ok, I’m sorry, I don’t know what I’m talking about :smile:

I was sure that at some point models well collected upfront, ie. router would run model hooks for all the needed routes and only when they all resolved, it would proceed to run the rest. However I can’t replicate this behaviour in really old versions of Ember.js, so I guess my memory is fooling me.

The thing that I want to achieve is something a bit different - I would like to fire all of the model hooks needed to render a page at once and then do everything else as it’s done today. I rarely need anything from a parent’s model in a child model hook - the point where parent is needed is most often setupController. Do you think that it’s a valid use case?

Aaah, right, I haven’t looked closely on setupController.

Just to illustrate what I’m talking about better, here is the implementation I would say it’s the closest: http://jsbin.com/ucanam/1909/edit

Both model hooks return promises, so we don’t need to worry about hacking the return values, but the promises are set at the same time, so page is loaded when the slowest promise loads.

We’ve been building a pretty robust application, and this proposal/behavior is absolutely essential. I am playing with 1.2 beta 3, and the progressive loading/error handling is fantastic.

I have come across an issue though. I’m not sure if this is the best place to post about it, so let me know if I should post it elsewhere.

If my nested/child promise rejects from a server error, for example, it will display my error template. However, if I attempt to transition away from the current error state back to the parent route that did resolve successfully, it will throw an error. This is using dynamic segments.

Example: /{folder-id}/item/{item-id}

Visiting this route successfully resolves the folder and renders the folder template, but the item promise rejects. The nested item/error template renders as it should. Trying to route back to the parent folder route, /{folder-id}, fails with Assertion failed: Cannot call get with 'id' on an undefined object.

The error appears to stem from the fact that it’s trying to transition back to the parent, but it doesn’t have the model/context, even though I’d imagine it should considering the parent route did successfully resolve its model. Have you come across or been alerted to this issue?

Running into the same issue myself and when I started to hack around this by overriding the error hook and passing in the parent model into the route, the error template wasn’t being added into the parent route’s outlet.

I think my issue is a combination of your issue and ember app kit.

I seem to be having problems with loading/ error substates and EAK. None of my loading templates or routes seem to be found… Was your problem related to EAK in the end?

Yes it was, but I can’t say how I even fixed it. It may have resolved itself when I rebased with the latest EAK master branch.

What is your issue, maybe I can help.

My issue is that loading and error substates (as described here) never seem to be entered. I’m presuming that I’m naming something wrong or putting it in the wrong place because it’s as if the loading templates I added don’t exist…

I last synced with EAK @ 808f6957… and can’t see anything which has been added to it since which might help.

My versions of ember etc are:

DEBUG: ------------------------------- 
DEBUG: Ember      : 1.2.0 
DEBUG: Ember Data : 1.0.0-beta.3 
DEBUG: Handlebars : 1.1.2 
DEBUG: jQuery     : 1.10.2 
DEBUG: ------------------------------- 

Do you have an example of the naming of routes and loading template files that works with EAK? I’m going to try and put together a reduced test case which shows the problem when I get a chance but maybe it’s something I can fix by seeing a full example…

Thanks!

You don’t need to touch the routes unless you plan on overriding the default substate behavior. Just to be clear, when you put the error or loading template instead of templates\error, templates\loading it doesn’t pick them up? Are so, are you returning false on the load or error actions within the application route or individual routes?

@machty I spent the last few days digging into Loading substate and I found that loading action helper parameters don’t include name of the origin route. I believe that second parameter is suppose to represent the originRoute, but originRoute.routeName is name of current route.

http://emberjs.jsbin.com/iYuPEpo/1/

Is this a bug?

@tarasm originRoute refers to the route that originated the “slow” promises that caused the loading action to fire. It’s not an ideal name but is kinda needed for internal purposes :confused:

So, if I want to know actions to be different depending on where the user came from, do I need to implement my own mechanism for tracking the user’s origin? or is there built in mechanism?

What’s the use case here?

(the use case might be totally valid but it’s possible this branching of behavior could/should live elsewhere, and not within the loading route)

From our IRC discussion:

I’m using the loading action to activate spinner on a portion of view. I want my loading mechanism to behave differently when transitioning inside of the same route or transitioning to another route. I’m taking advantage of the bubbling to show page wide spinner for transitioning from one route to another. Loading action is triggered on the slow route, but it doesn’t tell me where the user came from, so I don’t know if I should be bubbling or not.

I’m exploring my use case further following our conversation. I’ll post when I have more information.

Could you find out anything by now?

I want to use the cascading loading but I don’t want to show the loading page when transitioning to a sibling route. Can’t seem to find a proper way to achieve that.

Also I’m wondering if there is a way to specify a standard loading route that is used on every level, currently I’m creating the same template for every level {{loading-spinner}} which seems repetetive and stupid :smile: