Issue
I want to get the value of the eventID I have from my firestore collection called Events. I am able to fetch and show all my Events in my firestore collection in my app but I need this eventID to complete other functionalities.
I'm new to TS and Angular and can't understand why this is not working
When I log my userid variable inside the auth function it works fine and retrieves the value, but if I do so outside the function it gives undefined.
Also when I log the whole eventList variable that I created to store the info from firestore it logs all the information, but if I try to retrieve anything, for instance, this.eventList.eventID or this.eventList.title it logs undefined.
What am I doing wrong?
here is my code:
import { Component,OnInit } from '@angular/core';
import { AngularFirestore, AngularFirestoreCollection, AngularFirestoreDocument } from '@angular/fire/compat/firestore';
import { Observable } from 'rxjs/Observable';
import { AuthService } from '../auth.service';
import { Router } from '@angular/router';
import { async } from '@firebase/util';
export class Tab1Page implements OnInit {
public eventList;
public userid;
constructor(private firestore: AngularFirestore, public fAuth: AuthService, public router: Router) {}
ngOnInit(){
this.fAuth.firebaseAuth.user.subscribe(res => {
this.userid = res.uid; //current logged in user id
//fetch only events logged in user created
this.firestore.collection('Events',ref=>ref.where("eventCreator","==",this.userid)).valueChanges().subscribe(event => {
this.eventList = event
console.log(this.eventList)//logs all the info from firestore
console.log(this.eventList.eventID)//logs undefined
console.log(this.userid)//logs the userid
});
});
console.log(this.userid)//logs undefined
}
}
Solution
To get around the undefined data response issues that occurs with nested subscribes, use an RxJS switchMap() operator to pass the result of the outer observable from the fAuth.firebaseAuth.user observable into the inner observable, which is the this.firestore.collection.. observable, which from there you can assign the event list from the streamed response of the inner observable all within one subscription:
Like this (I am not sure about the structure of your event data - either it is an array or a class/interface that is a header containing an array so I have placed an any as the response type):
this.fAuth.firebaseAuth.user
.pipe(
switchMap((res: any) => {
this.userid = res.uid; //current logged in user id
//fetch only events logged in user created
const eventListObservable: Observable<any> =
this.firestore.collection('Events',ref =>
ref.where("eventCreator","==",res.uid))
.valueChanges()
.pipe(
map((event: any) =>
{
this.eventList = event;
console.log(event); //logs all the info from firestore
console.log(event.eventid); //logs event id
console.log(user.id); //logs the userid
return event;
})
);
return eventListObservable;
})
)
.subscribe();
As best practice, you can assign the above to a subscription and free it later in the ngDestroy() handler.
A common issue experienced is with being able to access variables outside of the subscribe() block and is raised in this question. If you try to access the component's event variable outside (and after) the subscribe() block, the variable will be undefined when it is accessed because the execution of the asynchronous inner observable has not yet completed and the code within it's handler has not yet been executed to initialize the variable.
Workarounds to the problem of variable access outside of the subscribe block include using:
- An
async pipewithin the component's HTML template. (Convert the variable to an Observable first). - Use another RxJS method such as
combinelatest()to subscribe to observables concurrently and handle them when they all have results ready from their respective observables. - Access the variable in another event handler from the HTML template.
To experiment and test the above nested observables use simple mock services first then attach your observables to the live services.
I recommend a good reference site here (which I also use quite often) for additional understanding (and examples) and more about how to use RxJS in these situations and of course other posts in SO.
Answered By - Andrew Halil
0 comments:
Post a Comment
Note: Only a member of this blog may post a comment.