1

I'm trying to push Firebase database values into a new array through an Ionic typescript file.

The problem is, I keep getting the error:

Error: Uncaught (in promise): TypeError: Cannot read property 'empList' of undefined

I can't really understand why because I'm still learning Typescript and have no idea what to do.

The firebase JSON looks like this:

- users
  - hJfEgXkyaKPckchL3kx8rpZ58Ew2
    -LV6c8E5rRD4_mQqsb6Q
      - name: "Emily Blunt"
      - points: 20
      - grade: 12

export class Tab1Page {
  name: string;
  grade: number;
  points: number;
  empList: Array<{name: string, grade: number, points: number}> = [];

  constructor() {
    const usersRef = firebase.database().ref('/users/');
    const ref = usersRef.orderByChild('points');
    
    ref.once('value').then(function(snap) {
      snap.forEach(function (childSnap) {
        const pkey = childSnap.key;
        // returns 'hJfEgXkyaKPckchL3kx8rpZ58Ew2'

        const keyRef = firebase.database().ref('/users/' + pkey);
        const ref2 = keyRef.orderByChild('name');

        ref2.once('value').then(function(snap) {
          snap.forEach(function (childSnap) {
            const key = childSnap.key;
            //returns -LV6c8E5rRD4_mQqsb6Q
            const firebaseRef = firebase.database().ref('/users/' + pkey + '/' + key);
            
            firebaseRef.once('value').then(function(snapshot) {
              const name = snapshot.val().name;
              const grade = snapshot.val().grade;
              const points = snapshot.val().points;
              // returns 'Emily Blunt', 12, 20
              this.empList.push({
                name: name,
                grade: grade,
                points: points
              });
            });
          });
        });
      });
    });
  }
}

Any help would be deeply appreciated.

caro
  • 365
  • 1
  • 4
  • 16

1 Answers1

3

The cause of your problem is a bad scoping of the this object in your firebase callback function. It actually refers to a Firebase.Promise. You need to save a reference to the this referring to your class, and then use this in the firebase callback :

export class Tab1Page {
  name: string;
  grade: number;
  points: number;
  empList: Array<{name: string, grade: number, points: number}> = [];

  constructor() {
    const usersRef = firebase.database().ref('/users/');
    const ref = usersRef.orderByChild('points');
    const self = this;
    ref.once('value').then(function(snap) {
      snap.forEach(function (childSnap) {
        const pkey = childSnap.key;
        // returns 'hJfEgXkyaKPckchL3kx8rpZ58Ew2'

        const keyRef = firebase.database().ref('/users/' + pkey);
        const ref2 = keyRef.orderByChild('name');

        ref2.once('value').then(function(snap) {
          snap.forEach(function (childSnap) {
            const key = childSnap.key;
            //returns -LV6c8E5rRD4_mQqsb6Q
            const firebaseRef = firebase.database().ref('/users/' + pkey + '/' + key);

            firebaseRef.once('value').then(function(snapshot) {
              const name = snapshot.val().name;
              const grade = snapshot.val().grade;
              const points = snapshot.val().points;
              // returns 'Emily Blunt', 12, 20
              self.empList.push({
                name: name,
                grade: grade,
                points: points
              });
            });
          });
        });
      });
    });
  }
}

You can see this another SO answer to have more details on the this binding : How does the this keword work

Pierre Criulanscy
  • 7,771
  • 3
  • 20
  • 36