Encountering a situation where the data retrieved from Firestore in Angular TypeScript is returning as

I am encountering an issue with retrieving the eventID value from my Events collection in Firestore. Although I am able to successfully display all the events in my app, I require the eventID for additional functionalities.

As someone new to TypeScript and Angular, I am struggling to understand why this functionality is not working as expected.

Inside the auth function, when I log the userid variable, it retrieves the value correctly. However, outside the function, it returns undefined.

Similarly, when I log the entire eventList variable which stores information from Firestore, it logs all the details. But attempting to retrieve specific values like this.eventList.eventID or this.eventList.title results in undefined.

What am I missing here?

Here is the relevant code snippet:

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 created by the logged-in user
      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
  }
}

Answer №1

To avoid issues with undefined data responses in nested subscribes, you can utilize the RxJS switchMap() operator. This allows you to pass the result of the outer observable from the fAuth.firebaseAuth.user observable to the inner observable (this.firestore.collection..). By doing this, you can handle the event list from the streamed response of the inner observable all within a single subscription:

Here is an example (assuming the structure of your event data - it could be an array or a class/interface containing an array, so I have used 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 created by the current user
        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();

It's a good practice to assign the above to a subscription and release it later in the ngDestroy() handler.

A common issue arises when trying to access variables outside the subscribe() block, as discussed in this question. To address this, consider using:

  1. An async pipe in the component's HTML template. (Convert the variable to an Observable first).
  2. Another RxJS method like combinelatest() to subscribe to observables concurrently and manage them once they all have results ready.
  3. Accessing the variable in another event handler from the HTML template.

For experimenting with nested observables, start with simple mock services before connecting to live services. Also, refer to a helpful site here for more insights on using RxJS in various scenarios.

Answer №2

When

console.log(this.userid) // logs undefined

It seems that @MikeOne mentioned that the functions inside subscribe are asynchronous. This means they will be executed at a later time. Therefore, when

console.log(this.userid)//logs undefined
is called, this.userid = res.uid; has not been executed yet.

Regarding

console.log(this.eventList.eventID) // logs undefined

It appears that this.eventList is an array. You might want to try accessing elements like this.eventList[0].eventID or iterate through the array to access each element individually.

Similar questions

If you have not found the answer to your question or you are interested in this topic, then look at other similar questions below or use the search

Tips for implementing 'transloco' on the 'pie-chart' component in an Angular project

Below is the code snippet: .HTML: <div fxFlex> <ngx-charts-pie-chart [view]="view" [scheme]="colorScheme" [results]="single0" ...

What is the best way to transfer image files into a specific folder?

I am currently in the process of developing a ReactJS web application. My goal is to upload images to a specific folder and then store the file name in the database for future use. Everything seems to be working smoothly up to this point, but I am facing ...

Display a second dialog to the left of the first dialog at the same level using Angular Material

Scenario: I have a customer record and would like to show additional read-only information in a separate dialog. This requires some selections. In Angular Material, I already have one modal dialog open and find it relatively easy to open a second one. Che ...

"Converting array into a string in TypeScript/Javascript, but unable to perform operations

After generating a string with the correct structure that includes an array, I am able to navigate through the JSON on sites like However, when attempting to access the array, it turns out that the array itself is null. Here is the scenario: Firstly, th ...

The firebase.d.ts on iOS functions properly, whereas on Android, it becomes

Currently, I am working with Ionic 2 on my Mac system. Your system information: Cordova CLI: 6.4.0 Ionic Framework Version: 2.0.0-rc.4 Ionic CLI Version: 2.1.18 Ionic App Lib Version: 2.1.9 Ionic App Scripts Version: 1.0.0 ios-deploy version: Not instal ...

What is the best way to implement a switch case for the value of a property within an object in a TypeScript file?

The object I'm dealing with looks like this: {a: auth?.type === '1' || auth?.type === '2' || auth?.type === '3' ? { reason: // I need to implement a switch case here : un ...

Nest is having trouble resolving dependencies for this service

Can multiple MongoDB models be injected into one resolver and used? I attempted to accomplish this by first adding the import of SectionSchema and SectionsService to the PostsModule: @Module({ imports: [MongooseModule.forFeature([{name: 'Post&apos ...

What is the method for inserting two dashes within a number?

For the output, I am looking to showcase a number in the following format => 979-9638403-03. At present, the number appears like this => 979963840303. portfolio.ts export class Portfolio { ... DEPO: number; /* DEPO */ const ...

issues arise with tests following the transition from Angular 9 to Angular 10

Recently, I encountered an issue with my jest-tests after updating Angular from version 9 to 10. These tests were working perfectly fine before the update. Can someone guide me on how to resolve this issue? Below is one of the tests that is causing troubl ...

Utilizing Firebase 3 with Ionic 2 and cordova-plugin-camera for seamless file uploading

I have been attempting to upload images to Firebase storage using the cordova-plugin-camera but have not been successful: Below is the code I have been using: let options:any = { quality : 100, destinationType : Camera.DestinationType.DATA_URL, ...

Is there a way to specify a type for a CSS color in TypeScript?

Consider this code snippet: type Color = string; interface Props { color: Color; text: string; } function Badge(props: Props) { return `<div style="color:${props.color}">${props.text}</div>`; } var badge = Badge({ color: &ap ...

React JS hosted externally along with just plain Javascript and HTML page

We are looking to implement a common widget on multiple services using ReactJS. The goal is to write client-side code for this widget as an external hosted JavaScript file that can be included in pages across different frameworks such as Angular, Inferno, ...

File handling in Angular 2 using Typescript involves understanding the fundamental syntax for managing files

Would someone be able to explain the fundamental syntax for reading and writing text files, also known as file handling in TypeScript? If there is a corresponding link that anyone could provide, it would be greatly appreciated. ...

Is there a way to disable the entire formgroup upon creation using FormBuilder?

While using the FormBuilder, I encountered an interesting challenge. For instance: formName = this.fb.group({ inputName: ['default value', Validators.required], // many other items }); (Example taken from: https://stackblitz.co ...

Setting default values for mat autocomplete is a useful feature for providing users with suggestions

Is it possible to display pre-selected values by default on auto complete when reloading the page? I have multiple auto completes on a page where users can select and save values. When the page is loaded again, I want the previously selected values to be d ...

Difficulty with two-dimensional arrays in Angular and Typescript

I am currently stuck trying to assign values to a 2-dimensional object array in Angular/Typescript. I have noticed that the last assignment seems to override the previous ones, but I cannot pinpoint why this is happening. Could someone please review my cod ...

Retrieve the non-empty attributes of a JSON object

I have a function in Typescript that extracts specific values from a JSON data object, some of which may be empty. How can I retrieve only certain data fields? Here is the function: let datosCod; for (let get in Object.keys(transfConsData)) { co ...

Tips for personalizing your Compodoc Angular documentation

I've been experimenting with adding extra side navigation menus to the current compodoc documentation. Here's an example of how I tried to accomplish this: menu-wc.js <li class="link"> <a href="dependencies.html" data-type="chapte ...

Truncate a string in Kendo Grid without any white spaces

While using a Kendo-Grid for filtering, I've come across an issue where my cell does not display the full string if there is no white space. The problem can be seen in the image below: For example, the string "https://www.linkedi/Testing" is only dis ...

Dealing with missing image sources in Angular 6 by catching errors and attempting to reset the source

When a user adds a blob to my list, sometimes the newly added image is still uploading when the list is refreshed. In this case, I catch the error and see the function starting at the right time: <img src="https://MyUrl/thumbnails/{{ blob.name }}" widt ...