Home > Software engineering >  getting undefined from data coming from firestore in Angular TypeScript
getting undefined from data coming from firestore in Angular TypeScript

Time:11-22

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
  }


}

CodePudding user response:

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.

CodePudding user response:

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.

To experiment and test the above nested observables use simple mock services first then attach your observables to the live services.

  • Related