I've been searching for a while trying to figure this out, I am most likely missing an obvious answer.
I have arrays of various types that get loaded in an injectable class when the app starts, data is loaded from backend api
Loading of the data is fine, I call the api and subscribe for the response, load it and away we go
But I have some components later on that depend on those lists having data as I may need to filter them in their OnInit's, how can I check/wait for those lists to be loaded?
ItemList class:
import { Injectable } from '@angular/core';
@Injectable({
providedIn: 'root',
})
export class ItemList {
....
....
public oneList: Map<string, string>;
public twoList: Object[];
....
}
InitLoader class:
import { Injectable } from '@angular/core';
import {HttpClient} from "@angular/common/http";
import { ItemList } from '../_common/constant/item-list';
@Injectable()
export class InitLoader {
constructor(private httpClient:HttpClient,
private itemList:ItemList) {}
public load() {
....
....
this.httpClient.get(url)
.subscribe( res =>{
...
...
this.itemList.oneList = res['oneListData'];
this.itemList.twoList = res['twoListData'];
...
...
}
}
}
In my app.component.ts I call the load() method
export class AppComponent implements OnInit {
...
...
constructor(private translate: TranslateService,
private router: Router ,
private initLoader:InitLoader,
private items:ItemList ) {
this.initLoader.load();
....
}
Then finally in a page component where I would like to use one of the lists, I need to do some work/filtering of a list in the ngOnInit(), which if the data hasn't loaded yet I will have issues
import { ItemList } from '../_common/constant/item-list';
@Component({
selector: 'page-one',
templateUrl: './page-one.component.html',
styleUrls: ['./page-one.component.less']
})
export class PageOneComponent implements OnInit {
constructor( public router: Router,
public items:ItemList) {
}
public ngOnInit() {
this.items.oneList.filter(x => x.value == "blah");
}
So in my PageOneComponent how can I check and wait for this list to be loaded so that I can then filter? This is in a modest sized project that is pretty far along with many other components that rely on these lists, so hoping to avoid some major restructuring
CodePudding user response:
You could create a BehaviourSubject
of the fields that you require in PageOneComponent
in your InitLoader Service. When you get the response in your InitLoader
load method, push that data into the BehaviourSubject
. Also, create a getter for that BehaviourSubject
for easy access.
Then in your PageOneComponent
, use the getter of that BehaviourSubject
to get the value only when it is loaded, or wait for it while being it is loaded using the subscribe method.
InitLoader Service
itemList$: BehaviorSubject<any> = new BehaviorSubject(undefined);
this.httpClient.get(url)
.subscribe( res =>{
...
...
this.itemList.oneList = res['oneListData'];
this.itemList.twoList = res['twoListData'];
this.itemList$.next(this.itemList);
...
...
}
getItemList(): BehaviorSubject<any> {
return this.itemList$;
}
PageOneComponent
import { ItemList } from '../_common/constant/item-list';
@Component({
selector: 'page-one',
templateUrl: './page-one.component.html',
styleUrls: ['./page-one.component.less']
})
export class PageOneComponent implements OnInit {
constructor(
public router: Router,
public items: ItemList,
private initLoader: InitLoader) {}
public ngOnInit() {
this.initLoader.getItemList().subscribe(
resp => {
if(!resp) {
console.log(resp);
//Do your filtering etc here
}
}
);
}
}