Just a note: I am aware of the existence of
APP_INITIALIZER
, but it appears to only work in the top-level module (app.module.ts) of the application.
I have a parent component that loads some data:
In admin-area.component.ts:
ngOnInit(): void {
forkJoin([
this._userService.getMe(),
this._placeService.getAll()
])
.pipe(finalize(() => this.afterInit()))
.subscribe(
([user, businesses]) => {
this._appState.user = user;
this._appState.businesses = businesses;
this.afterInit();
}
);
}
The issue arises with child components relying on this._appState.user
and this._appState.businesses
.
Loading this with APP_INITIALIZER
isn't possible as the above data is only loaded when the user is logged in. The "logged-in" area is within a lazy-loaded module of its own.
So, the question here is simple:
How can I ensure that my data is loaded before child components attempt to display themselves?
This approach:
providers: [
AdminAreaState,
{ provide: APP_INITIALIZER, useFactory: adminAreaInit, deps: [AdminAreaState], multi: true}
]
Hasn't been successful. adminAreaInit()
isn't being called. It seems like APP_INITIALIZER
only works for the main module app.module.ts. Is that correct?
What other options do I have?
I believe more details are necessary.
Note that I'm attempting to utilize *ngIf
:
<div *ngIf="!business?.servicePlan">
Please Upgrade
</div>
However, the problem occurs when I navigate to this page and refresh the page, where business
is always undefined
. It's a result of finding the right business
in the Array of businesses
using the businessId
.
At the time the child component gets loaded, additional data is fetched. In this case, some reviews (comments).
Now, loadPage()
fetches one page of the requested data for a business. _appState
is supposed to be loaded first. If I try this:
private loadPage() {
console.log(this._appState);
console.log(this._appState.businesses);
this._appState.businesses.forEach(
(b) => {
console.log(b);
});
setTimeout(() => this._appState.businesses.forEach(
(b) => {
console.log(b);
}
), 100);
const businessId = this._appState.businessId;
this.business = this._appState.businesses.find(b => b.id === businessId);
}
This is what I get:
https://i.sstatic.net/P8t1t.png
As shown, this._appState
contains businesses, but this._appState.businesses
prints an empty array.
_appState.businesses
is just an Observable
:
ApplicationState
service:
@Injectable()
export class ApplicationState {
public businessIdChange;
public businessesChange;
private _user = new BehaviorSubject<UserModel>(null);
private _businessId = new BehaviorSubject<number>(null);
private _businesses = new BehaviorSubject<Array<BusinessModel>>([]);
constructor() {
this.businessIdChange = this._businessId.asObservable();
this.businessesChange = this._businesses.asObservable();
}
set user(value: UserModel) {
this._user.next(value);
}
get user(): UserModel {
return this._user.getValue();
}
set businessId(businessId: number) {
if (businessId === this.businessId) {
return;
}
this._businessId.next(businessId);
}
get businessId() {
return this._businessId.getValue();
}
set businesses(value) {
this._businesses.next(value);
}
get businesses(): Array<BusinessModel> {
return this._businesses.getValue();
}
}
I'm unsure why this is happening and I thought pre-loading the data would make sense anyway. Could there be another underlying issue here?