Reputation: 12838
I'm using Aurelia's EventAggregator
to publish and subscribe to events in my app. Some of my custom elements take a while to load, so I've used a loading
event to tell my main app.js
to add a spinner to the page during loading.
This works fine once the app has loaded and I start switching between routes, however, on first page load the event doesn't seem to fire - or at least, it isn't picked up by the subscribe
method.
Here's basically what my app.js
does:
attached () {
this.mainLoadingSubscription = this.eventAggregator.subscribe('main:loading', isLoading => {
// If main is loading
if (isLoading) {
document.documentElement.classList.add('main-loading');
}
// Stopped loading
else {
document.documentElement.classList.remove('main-loading');
}
});
}
And here's what my custom elements do:
constructor () {
this.eventAggregator.publish('main:loading', true);
}
attached () {
this.doSomeAsyncAction.then(() => {
this.eventAggregator.publish('main:loading', false);
});
}
This causes the first page load to not show a spinner and instead the page looks kind of broken.
Btw, I am aware of the fact that you can return a Promise
from the element's attached
method but I can't do this because of this other problem
Upvotes: 1
Views: 1012
Reputation: 12295
In the above example, you set up subscriptions in the viewModel's attached()
callback. Unfortunately, this will not be called until all child custom element's attached()
callbacks are called, which is long after any one custom element's constructor()
function is called.
Try this:
app.js
@inject(EventAggregator)
export class AppViewModel {
constructor(eventAggregator) {
this.mainLoadingSubscription = eventAggregator.subscribe('main:loading', isLoading => {
// do your thing
}
}
}
If the viewModel is a route that can be navigated to, then handle this in the activate()
callback with appropriate teardown in the deactivate()
callback.
@inject(EventAggregator)
export class AppViewModel {
constructor(eventAggregator) {
this.eventAggregator = eventAggregator;
}
activate() {
this.mainLoadingSubscription = this.eventAggregator.subscribe('main:loading', isLoading => {
// do your thing
}
}
deactivate() {
this.mainLoadingSubscription.dispose();
}
}
Upvotes: 2