This course has been updated! We now recommend you take the Ember Octane Fundamentals course.
Transcript from the "Loading & Error Substates Revisited" Lesson
>> Mike North: So without further ado, let's give loading and substates another shot. So, the general idea behind the loading substate is it is a state within the router, which is a finite state machine that doesn't correspond to a URL. And it will be active as long as the router is waiting for one of the async hooks on a given route for its promise to resolve.
[00:00:34] So if you're waiting for data to come back from an API, you'll be in the loading substate. By default, there really is no visual change to the UI as a result of returning a promise from one of these async hooks on route. You'll just see that you end up waiting on the previous screen and it sort of hangs there for a second, and then you'll end up at the destination.
[00:01:01] One reason that this could be desirable to have this be the default is that if you have very short waits, you don't wanna see transitions to a blank screen or you don't want a flash of some kind if you only have like 150-millisecond wait. And so by default it's sort of disabled.
[00:01:21] All you have to do to take advantage of the loading substate is add a template in the correct folder, depending on where you're pivoting in your tree, in your tree of you know routes. And that loading .HPS will be rendered in the same outlet that is basically changing it's content while you're in this loading situation.
>> Mike North: The error substate works similarly and you can see here this dash line I have from the error substate up to the post route. I just wanted to illustrate that in both of these cases, for loading and for error, the easy way to think about which loading substate or which error substate you're going to need to customize for a given situation.
[00:02:17] It completely depends on what you're pivoting on. What is the node in this tree of routes that you're actually pivoting on to make a given transition? And so here, because we're pivoting from post index to post comments index and the highest common ancestor of those two states is this post route.
[00:02:43] It will be the template for this would be template/post/error.hbs if that make sense.
>> Mike North: So remember that these are part of the route hierarchy. The significance here is that you can get specific when loading a particular thing. If it's make sense to handle a certain loading events or a certain error events in a way that is unique to a particular set of routes.
[00:03:18] Remember to mentally or even on paper draw your route hierarchy because it is quite easy to get confused about which loading HPS is gonna be showing up at a particular time. And also if you have to kick out to another substate of some sort, like if you had custom error page, intermediate transition to.
[00:03:45] You can think of this as being another option in addition to transition to and replace with which we already discussed they're ways of changing your current state. Intermediate transition to will take you to a state but not change the URL. And so if you wanted a URL to remain the same but to go to a specific error page in a specific case, intermediateTransitionTo, and then the name of that special error route would be how to go about doing that.
>> Mike North: So the error substate and it's worth noting the loading substate does the same thing. They will fire an action on the route that you're pivoting on. So going back to this example that we were looking at earlier. Here, the post route is where you're gonna see an error action being fired or a loading action being fired.
>> Mike North: Returning true will cause the action to bubble up to parent routes. Eventually, you'll reach application route and the default behavior for the error action is to enter the errors substate. So basically, you have an opportunity here to handle things specifically any given route and then to have sort of a catch all at a higher level.
[00:05:15] And if you breakout your gang of four design patterns book, this is commonly known as the chain of responsibility design pattern. And the idea is that you have several different objects that have a chance to handle a given thing and they can accept responsibility and deal with it or they can pass it up the chain.
[00:05:39] Or in this case, they could do both. They could do something and also pass it up the chain.
>> Mike North: So just to illustrate how that works, if an error happened in this case, if we say our model hook promise rejected, the error action be called here and then, it would be called here.
[00:06:04] And so typically in your application route, you don't wanna have some general more handling of code of some sort. If you're instrumenting is a bigger place to start sending things off to whatever collector you happen to be using... But for things like the 404 or a common thing is if you get a 401 or a 403 and you need to kick a user out to log in page because their session may have expired.
[00:06:32] That is something you can handle specifically and sort of let everything else fall through to a general or handling code path. Does everyone get how that works?
>> Speaker 2: Is return true a default? I missed that.
>> Mike North: So, you have to explicitly return it true. If you implement an action, the default is you're handling it.
[00:06:57] Returning true is opting into allow it to continue bubbling up.
>> Speaker 2: If you don't explicitly define the action, will it bubble?
>> Mike North: If you don't define an action, it will bubble. If you define an action and return nothing at all, it won't bubble. If you define an action and return true, your action will run and it will bubble.
[00:07:19] So those are the three things. Do nothing about it, do something about it and accept total responsibility for it, do something and allow other things up to change to do something as well