Search code examples
angulartypescriptfirebase-realtime-databaseionic4angularfire

How to get Data as Object from Firebase to Service and then to Page correctly (Angularfire + ionic4)?


I am trying to get data from Firebase Realtimedatabase to my mypage.page via firebase.service:

  • I can get simple data (strings for example) inside the firebase.service and mypage.page, but I can’t load objects into mypage.page.
  • In console I get bunch of error messages Cannot read properties of undefined (reading 'id').

Console log:

core.js:6479 ERROR TypeError: Cannot read properties of undefined (reading 'id')
    at MypagePage_Template (template.html:8)
    at executeTemplate (core.js:9598)
    at refreshView (core.js:9464)
    at refreshComponent (core.js:10635)
    at refreshChildComponents (core.js:9261)
    at refreshView (core.js:9514)
    at refreshEmbeddedViews (core.js:10589)
    at refreshView (core.js:9488)
    at refreshComponent (core.js:10635)
    at refreshChildComponents (core.js:9261)

How can I pass Object through Promise from firebase.service to mypage.page?


Parent question.

mypage.page.ts code:

import { Component, OnInit } from '@angular/core';
import { DataObject, FirebaseService } from '../firebase.service';

@Component({
  selector: 'app-mypage',
  templateUrl: './mypage.page.html',
  styleUrls: ['./mypage.page.scss'],
})
export class MypagePage implements OnInit {
  localData: DataObject;

  constructor(private firebaseService: FirebaseService) {
    this.firebaseService.getData().then(data => {
      this.localData = data;
   }).catch((error) => {
    console.error(error);
  });
  }

  ngOnInit() {
  }

}

firebase.service.ts code:

import { Injectable } from '@angular/core';
import { AngularFireDatabase } from '@angular/fire/compat/database';
import { DatabaseReference } from '@angular/fire/compat/database/interfaces';

export interface DataObject{
  id: string;
  data: string;
}

@Injectable({
  providedIn: 'root'
})
export class FirebaseService {
  databaseRef: DatabaseReference;

  constructor(private db: AngularFireDatabase) {
    this.databaseRef = db.database.ref(); //Create databaseReference
  }

  getData(): Promise<any> {
    return this.databaseRef.child('data').get().then((snapshot) => {
      if (snapshot.exists()) {
        return {id: '1', data: snapshot.val()};
      } else {
        return null;
      }
    }).catch((error) => {
      console.error(error);
    });
  }
}

mypage.page.html code:

<ion-header>
  <ion-toolbar>
    <ion-title>mypage</ion-title>
  </ion-toolbar>
</ion-header>

<ion-content>
  <ion-label>{{ localData.id }}</ion-label>
</ion-content>

Solution

  • This should work as expected, the error that you get is because the localData is indeed undefined until the data comes from the network.

    You have 2 solutions for this:

    1. Either give localData an initial value, so it's no longer undefined:
    export class MypagePage implements OnInit {
      localData: Partial<DataObject> = {};
      // ...
    }
    
    1. Put an ngIf on the label and just don't display it while the data is not there yet:
    <ion-content>
      <ion-label *ngIf="localData">{{ localData.id }}</ion-label>
    </ion-content>