I can find nothing that tells me the order of the components lifecycle with respect to other components.
Nor how the routing lifecycle is interweaved with the component lifecycle.
The best I can find is related to Dialogs.
Order of Invocation
Each dialog instance goes through the full lifecycle once.
.canActivate() - aurelia-dialog specific
.activate() - aurelia-dialog specific
.created() - as defined by aurelia-templating
.bind() - as defined by aurelia-templating
.attached() - as defined by aurelia-templating
.canDeactivate() - aurelia-dialog specific
.deactivate() - aurelia-dialog specific
.detached() - as defined by aurelia-templating
.unbind() - as defined by aurelia-templating
If I’m trying to share application state I need to know which component should be creating that state.
My current assumption was that custom elements higher up in the DOM would have their lifecycle called first so that its children would have whatever was needed by the time it was their turn for the lifecycle events.
Whacking in some debugs is showing me:
- activate on Parent
- activate on Child
- created on Child
- bind on Child
- created on Parent
- bind on Parent
- attached on Parent
- attached on Child
I’ll have to ponder this some more.
What advice do you have for me?
If I have remote resources that need obtaining where is the correct place in the lifecycle to fetch them?
Note the wrong order of bind (parent should be before child) is a know bug (introduced by a fix to another bug).
That’s not the only lifecycle ordering bug, there is another one in child route https://github.com/aurelia/router/pull/571.
It was left as it is, because of current router has no enough test coverage. We are afraid of introducing another bug from another fix.
On the other side, Aurelia 2 has made it deadly clear about the lifecycle orders in test cases.
In router components, I do remote fetch in activate.
In other custom elements, I do remote fetch in attached.
You can return a promise in all callbacks.
When remote fetch is slow, I recommend to have a global spinner, so that you don’t have to do spinner in every single route pages.
In top template (like
debounce means you don’t show spinner if it’s quicker than 200ms (default debounce delay).
if.bind="router.isNavigating || fetchClient.isRequesting & debounce"
Where is the
return a promise in all callbacks documented?
activate supports that because https://aurelia.io/docs/fundamentals/cheat-sheet#routing says so.
I’m sure I tried returning a Promise for other callbacks and it wasn’t working as I thought it might, and since I couldn’t find the docs to say otherwise I assumed Promises were not
Thanks for your thoughts, I’ll ponder what I should do properly some more.
I could not find proper document either @bigopon do you know is this documented?
They do accept promise return, Aurelia will wait for them. This is a nice feature since Durandaljs (although I did not use it) before Aurelia. Async/await is same, it is syntax sugar for promise. (I was all wrong )
Show me your code which wasn’t working as you thought.
That code is long gone
I was hacking to see why things were not working the way I expected, which I assume is my lack of understanding rather than bugs.
I’ve tried returning a
bind expecting that to halt any further components
bind being called, or at the least to wait until resolving before moving on to the further steps in the lifecycle like
But its not.
I don’t have a small reproducible test case yet. If I can sort out my production code I’ll work on that after.
You are right. I was wrong. It looks like bind did not wait on promise. I will check if this is intentional. For now, use attached to wait on remote fetch.
The templating lifecycles have never awaited promises in v1, only the router lifecycles do. In v1 you normally fetch data in
activate rather than in
bind. It’s possible though with composition transactions.
In v2 you can return a promise from
bind and it will be awaited
I was all wrong no wonder no documentation.
Only router lifecycle canActivate, activate, canDeactive, deactivate supports promise return.
I return promise in attached, but it actually renders before the promise is resolved.
I wish I could find the damn web article. It’s something along the lines of ensuring you test your component when it doesn’t have data.
I know its the way our components are (poorly) written. Right now the component fetches from the server to retrieve the settings for the component, as we persist those settings and its changes.
I’ve got a place holder for Improving vCurrent docs and it may very well be the way I look at the lifecycle hooks, but because
and it hasn’t been
activate doesn’t have anything injected into it
created I don’t think
activate is the correct place to fetch those values and then store them into the object as its not at the right stage in the lifecycle for touching member properties.
Yet if I don’t do it there the child components that depend on those settings won’t have anything available yet.
The code currently does the fetch and setting of
this member properties in the
activate and so I’m attempting to clean up the code and document what each lifecycle’s purpose is for and what types of things you should be doing in that method. We don’t have that level of understanding internally yet.
Note: My claim that it didn’t have anything injected into it was because it was a fresh restart of the server and the injected object hadn’t been setup yet. The
constructor is the first thing in the lifecycle, which includes all injected properties. Whether your code has setup those objects is your problem, not Aurelia’s.
activate callback is before
bind, that is a debatable decision. But it doesn’t matter because you don’t have any binding on a route component.
activate callback is designed for you to fetch remote data before rendering route component. This is demonstrated in tutorial. https://aurelia.io/docs/tutorials/creating-a-contact-manager#building-out-the-contact-detail-screen
Its very likely that our component is doing too much and should be broken into 2 components.
One to do the routing, one to do UI.
That expert advice is definitely something I want to add to the documentation.