I have a calendar inside an Angular app (calendarComponent) that gets its entries via firebase cloud functions from a mongodb (via Service called calendarService). To create a new entry, im popping up an angular material dialog (addEventComponent). This Dialog needs some data from the database to work. Until now the dialog component requests the data from the calendarService, which does a new http request every time i want to add an entry. Besides having noticeable delay it may trigger increased costs depending on the firebase data plan. Ideally the calendarComponent would request the data from the calendarService on ngOnInit and pass it to the addEventComponent on request, but this only works if the http request is finished when the new Entry dialog is clicked. Im too unexperienced with angular and rxjs to get this problem solved in a not ugly way.
What i initially tried was something like this:
Inside the calendarComponent
requiredData: RequiredData[];
ngOnInit() {
this.calendarService.getRequiredData().subscribe(response => {
this.requiredData = response.data;
});
}
addNewEntry () {
const dialogData = this.requiredData;
const dialogRef = this.dialogModal.open(AddEventComponent, {
data: { requiredData: dialogData },
});
}
(The CalendarService just returns a http.get() request so i didnt write the code here.)
As long as the http request doenst take forever, it works great. As a temporary solution i triggered the http request as before but saved the response in the calenderService and returned an observable of that. That looks like this:
Inside the calendarComponent
ngOnInit() {
this.calendarService.getRequiredData();
}
Inside the calendarService
private requiredData$ = new Subject<RequiredData>();
requiredData: RequiredData[];
getRequiredData () {
this.http.get<{ _msg: string, reqData: RequiredData[] }>(API_URL)
.subscribe(response => {
this.requiredData = response.reqData;
this.requiredData$.next([...this.requiredData]);
});
}
getReqData () {
return this.requiredData$.asObservable();
}
My problem occurs inside the AddEventComponent
requiredData: RequiredData[];
ngOnInit() {
this.calendarService.getReqData().subscribe(response => {
this.useTheRequiredData(response);
});
}
The above code wouldnt work, because the subscription doenst trigger if the request already finished. So what i would need is a smarter way to do this or a code that checks if the observable already emitted values and if not waits for the first emit and then triggers the follow up functions. Kinda like the following but in less gross and working.
inside the AddEventComponent
requiredData: RequiredData[];
ngOnInit() {
if (this.calendarService.requiredData) {
this.useTheRequiredData(this.calendarService.requiredData);
} else {
this.calendarService.getReqData().subscribe(response => {
this.useTheRequiredData(response);
});
}
}
Every help is appreciated.
What seems to work is (AddEventComponent)
this.calendarService.requiredData
? this.useTheRequiredData(this.calendarService.requiredData)
: this.calendarService.getReqData().pipe(
take(1),
tap(response => {
this.useTheRequiredData(response);
})
).subscribe();
What mainly confused me was using a pure pipe (angular filter pipe within the template, not the rxjs pipe), didnt realise that pretty long.