Firebase is storing object values as 'undefined'

My goal is to retrieve user details from my firebase database while using Ionic and Typescript.

Here is how I add a user:

addToDatabase(user: User) {
let isInstructor = user.isInstructor == null ? false : user.isInstructor;
this.afDB.list("/users/").push(
  {
    "firstName": user.firstName,
    "lastName": user.lastName,
    "email": user.email,
    "institution" : user.institution,
    "isInstructor": isInstructor
  }
);
}

The user is successfully created

Next, I access the data in this manner:

  async signIn(user: User) {
this.afAuth.auth.signInWithEmailAndPassword(user.email, user.password).then((result) => {

  var ref = this.afDB.database.ref("users/");

  //retrieve values for a single user by email 
  ref.orderByChild("email").equalTo(user.email).once("value").then(function (snapshot) {
    console.log(snapshot.val());
    var value = snapshot.val();
    console.log(value);
    var firstName = value.firstName;
    console.log(value.firstName);
    var lastName = JSON.stringify(value.lastName);
    console.log(lastName);

    //user.firstName = value.firstName; Save user details here
    //user.lastName = value.lastName;  and here for later
  }, function (errorObject) {
    console.log("The read failed: " + errorObject.code);
  });

  this.shareService.setUserDetails(user); //User detail is shared in the app

  this.navCtrl.setRoot(HomePage);
}).catch(function (error) {
  alert("Sign in failed:\n" + error.message);
  });
}

This part appears to be functioning correctly as I can view the user object in Chrome.

However, when attempting to display the object on the page's HTML, it often shows up as "undefined."

var value = snapshot.val();
console.log(value); //Displays the object as expected
console.log(value.firstName); //Desired property but returns "undefined"
var lastName = JSON.stringify(value.lastName); //Attempt to stringify
console.log(lastName); //Still "undefined"

I've explored various solutions not included in the provided code. Yet, I am unable to obtain the desired data.

Update: I've added the JSON export of my database for reference:

{
  "users" : {
    "-L6JNUj7T9wvssjiWjX9" : {
      "email" : "<a href="/cdn-cgi/l/email-protection" class="__cf_email__" data-cfemail="e195849295a195849295cf828e8c">[email protected]</a>",
      "firstName" : "testFirst",
      "institution" : "school-university",
      "isInstructor" : false,
      "lastName" : "testLast"
    }
  }
}

Update: Attempting to use promises also results in returning null.

public dataTest(user: User) {
var ref = this.afDB.database.ref("users/");
return new Promise(function (resolve, reject) {
  try {
    ref.once('value', function (snapshot) {
      if (typeof snapshot.val().firstName === 'undefined') {
        resolve(null);
      } else {
        console.log(snapshot.val().firstName);
        resolve(snapshot.val().firstName);
      }
    })
  } catch (e) {
    reject(e)
  }
});
}

  this.dataTest(user).then(function (result) {
    console.log("result " + result) //Returns null
  }).catch(function (error) {
    console.log(error)
  })

Answer №1

Feel free to use this code snippet. It's guaranteed to work flawlessly.

const reference = this.afDB.database.ref("users/");
reference.orderByChild("email").equalTo(user.email).once("value", (items : any) => 
{
    console.log("Key: ", items.key);
    console.log("Value: ", items.val());

    let usersData : any[] = [];

    items.forEach((item) =>
    {
        usersData.push({
            key           : item.key,
            firstName     : item.val().firstName,
            lastName      : item.val().lastName,
            email         : item.val().email,
            isInstructor  : item.val().isInstructor
        });
    });
    console.log("All Users Data: ", usersData);
    this.userData = usersData;
});

Answer №2

Upon reflection, I realized that my main issue stemmed from not considering the key generated by the .push method. While I was delving into the JSON object, I neglected to include the key in the path, resulting in all values showing up as "undefined".

As a solution, we opted to modify our user registration process. Instead of utilizing .push and generating a key, we decided to use the user's email as the key. Due to Firebase's restrictions on certain characters within keys, we implemented a code snippet to remove these special characters before storing the key. This way, we can compare against it to access specific user data. Admittedly, this may not be the most graceful design, but as students navigating our way through, we are constantly learning and adapting.

The revised function for adding user data to Firebase:

addToDatabase(user: User) {
if (!user.isInstructor) {
  this.afDB.list("users/students/").set(
    user.email
        // Remove disallowed characters from key
        .replace('.', '')
        .replace('#', '')
        .replace('$', '')
        .replace('[', '')
        .replace(']', ''),
    {
      "firstName": user.firstName,
      "lastName": user.lastName,
      "email": user.email,
      "institution" : user.institution,
      "isInstructor": user.isInstructor
    }
  );
} //more repetitive code if a user is an instructor below this

The updated signIn function retrieves a user's data, identifies their identity, gathers their information, organizes it into a user object, and forwards it to our share service for universal access throughout the application.

async signIn(user: User) {
this.afAuth.auth.signInWithEmailAndPassword(user.email, user.password).then((result) => {
  var usersRef = this.afDB.database.ref("users/");
  // Locate user in database
  this.afDB.database.ref("users/students").child(
    user.email
      .replace('.', '')
      .replace('#', '')
      .replace('$', '')
      .replace('[', '')
      .replace(']', ''))
        .once("value", function(snapshot) {

    // Retrieve user info
    user.firstName = snapshot.child("firstName").val();
    user.lastName = snapshot.child("lastName").val();
    user.email = snapshot.child("email").val();

  }).then((result) => {
    this.shareService.setUserDetails(user);
    this.navCtrl.setRoot(HomePage);
  });
}).catch(function (error) {
  alert("Sign in failed:\n" + error.message);
});
}

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

Threading in Node.js for Optimized Performance

Having trouble making axios calls in worker threads Hello, I'm working on a Node.js application and attempting to utilize worker threads for one specific task. Within the worker thread, I need to make an axios call, but I keep encountering an error w ...

Concealing Dropdown Box Information Based on a Customized List in Angular

Is there a way to remove an item from a dropdown list once it has been selected? For example, if I have a dropdown box with options 'Dog', 'Lion', and 'Cat', how can I make it so that once I select 'Dog', it will no ...

Find the appropriate return type for a TypeScript function based on its argument

Is it feasible in TypeScript to infer the return type of a function based on its arguments? This feature would be beneficial when extracting specific properties from, for example, a database query. Here is an illustration (https://repl.it/repls/Irresponsi ...

Can someone explain how to implement document.querySelector in TypeScript within the Angular framework?

I am tackling the task of creating a login/register form that allows users to switch between the two forms with the click of a button. The goal is to only display one form at a time. Initially, I implemented this functionality in a basic HTML file and it w ...

I am encountering an issue where body-parser is not functioning properly with typescript. Whenever I make a request, the request.body is returning as undefined

Below is the code snippet for my Express application using TypeScript version 3.7.4: import bodyParser from "body-parser"; import config from "config"; import cookieParser from "cookie-parser"; import express from "express"; import mongoose from "mongoose ...

What is the most effective method for designing a scalable menu?

What is the most effective way to create a menu similar to the examples in the attached photos? I attempted to achieve this using the following code: const [firstParentActive, setFirstParentActive] = useState(false) // my approach was to use useState for ...

Tips for personalizing Ion text area in Ionic?

Seeking assistance on how to effectively utilize ion-textarea. As a novice in the realm of Ionic, I am encountering various challenges while working with this feature. The issue lies in the fact that instead of displaying a scrollbar on the right side, the ...

Issue with Ionic 4 IOS deeplinks: Instead of opening in the app, they redirect to the browser

After working diligently to establish deeplinks for my Ionic 4 iOS application, I meticulously followed a series of steps to achieve this goal: I uploaded an Apple site association file to the web version of the app, ensuring the utilization of the prec ...

The error message "Unable to access property 'open' of an undefined menu" is being displayed in a TypeScript code

I am facing an issue with the action in my menu. For this project, I am using a material menu and icons. The main menu code appears as follows: <mat-menu #rootMenu="matMenu" [overlapTrigger]="false"> <ng-template matMenuContent let-element="ele ...

What is the best way to prevent event propagation in d3 with TypeScript?

When working with JavaScript, I often use the following code to prevent event propagation when dragging something. var drag = d3.behavior.drag() .origin(function(d) { return d; }) .on('dragstart', function(e) { d3.event.sourceEvent ...

The behavior of the Ionic checkbox in version 5 seems to be quite delayed

I am facing an issue with binding the checked attribute value on an ion-checkbox, as the behavior seems to be delayed. In my .ts file, I have an array variable named user_id. In my checkbox list, I am trying to populate this array based on which checkboxe ...

The form will not appear if there is no data bound to it

Can anyone help me with displaying the form even when the data is empty in my template? <form class="nobottommargin" *ngIf="details" [formGroup]="form" (ngSubmit)="onSubmit(form.value)" name="template-contactform"> <div class="col-sm-12 nopad ...

Wait until a svelte store value is set to true before fetching data (TypeScript)

I have implemented a pop-up prompt that requests the user's year group. Since I have databases for each year group, I need to trigger a function once the value of userInfo changes to true. My JavaScript skills are limited, and my experience has been ...

Utilizing React Router with the power of useCallback

My route configuration is set up as follows: const defineRoutes = (): React.ReactElement => ( <Switch> <Redirect exact from="/" to="/estimates" /> <Route exact path="/estimates" component={CostingPa ...

When utilizing Google Analytics in conjunction with Next.Js, encountering the error message "window.gtag is not

Encountering an error on page load with the message: window.gtag is not a function Using Next.js version 14.0.4. All existing solutions seem to hinder data collection, preventing the website from setting cookie consent correctly. I am uncertain about the ...

What is the implementation of booleans within the Promise.all() function?

I am looking to implement a functionality like the following: statusReady: boolean = false; jobsReady: boolean = false; ready() { return Promise.all([statusReady, jobsReady]); } ...with the goal of being able to do this later on: this.ready().then(() ...

Add flexible templates into List element in Ionic version 3

My Progress Being a newcomer to ionic, I successfully created a List component in ionic 3 that retrieves JSON data from the server and displays it as a list layout on specified pages using a list selector. Objective I am looking to showcase various list ...

Standardized identification code

My request response needs to be defined, but the key name may vary. It will always be a string, but the specific key depends on the request. These are the possible responses: { someRequest: { message: 'success', status: 200 } } { someOtherReques ...

Include a control within a form based on the Observable response

I am looking to enhance my form by adding a control of array type, but I need to wait for the return of an Observable before mapping the values and integrating them into the form. The issue with the current code is that it inserts an empty array control e ...

Is it possible to create a class object with properties directly from the constructor, without needing to cast a custom constructor signature

class __Constants__ { [key: string]: string; constructor(values: string[]) { values.forEach((key) => { this[key] = key; }); } } const Constants = __Constants__ as { new <T extends readonly string[]>(values: T): { [k in T[num ...