Reputation: 939
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
}
}
Upvotes: 1
Views: 706
Reputation: 1319
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:
async pipe
within the component's HTML template. (Convert the
variable to an Observable first).combinelatest()
to subscribe to
observables concurrently and handle them when they all have results
ready from their respective observables.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.
Upvotes: 2
Reputation: 4192
As console.log(this.userid) // logs undefined
As @MikeOne
refers functions inside subscribe
is asyncronous. These function will usually be executed later. So at the timing console.log(this.userid)//logs undefined
is executed, this.userid = res.uid;
still not be executed.
As console.log(this.eventList.eventID) // logs undefined
I guess this.eventList
is array. Try this.eventList[0].eventID
and so on to access each element.
Upvotes: 0