Why does firebase data not load on html template in ionic

I have been trying to retrieve data from database using ionic. The problem is the data is not displayed on my ionic page no matter what I try. I even tried from tutorials like: https://ionicthemes.com/tutorials/about/building-a-ionic-firebase-app-step-by-step and https://www.javatpoint.com/ionic-firebase (which turns up similar to what I have been doing) just incase I was wrong or out of touch but still the same issue. After searching online for help without success, I reverted back to the original, and the problem is it just display a blank page and it doesn;t give any errors, kindly assist. Here is my code :

For service.ts

import { Injectable } from '@angular/core';
import { AngularFirestore, AngularFirestoreCollection } from '@angular/fire/firestore';
import { AngularFireAuth } from '@angular/fire/auth';
import * as firebase from 'firebase';
import { Observable } from 'rxjs';
import { map } from 'rxjs/operators';

export interface Location {
  id: string;
    title: string;
    area: number;
    location: string;
    description: Text;
    image: string;
}

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

  private snapshotChangesSubscription: any;
  public currentUser: any;
  private user:any;
  locations: Observable<Location[]>;
  locationsCollection: AngularFirestoreCollection<Location>;

  constructor(
    public afs: AngularFirestore,
    public afAuth: AngularFireAuth
  ){
    this.afAuth.onAuthStateChanged(res => {
      if(res){
       this.user = res;
       console.log('User '+res.uid+' is logged in');
       this.locationsCollection = this.afs.collection<Location>
      //  ('people').doc(res.uid).collection('locations');
       (
         `people/${res.uid}/locations`,
         ref => ref.orderBy('timestamp')
       );

       this.locations = this.locationsCollection.snapshotChanges().pipe(
         map(actions =>{
           return actions.map(a => {
            // console.log('User '+res.uid+' is still logged in');
             const data = a.payload.doc.data();
             const id = a.payload.doc.id;
             return { id, ...data };
           });
          })
       );
      }
      });
  }

  getLocations():Observable<Locations[]>{
      return this.locations;
  }

For component:

import { Component, OnInit } from '@angular/core';
import { LoadingController } from '@ionic/angular';
import { FirebaseService, Location } from '../service/firebase.service';
import {AngularFirestoreCollection } from '@angular/fire/firestore';
import { Observable } from 'rxjs';

@Component({
  selector: 'app-locations',
  templateUrl: './locations.page.html',
  styleUrls: ['./locations.page.scss'],
})
export class LocationsPage implements OnInit {

  locations: Observable<Location[]>;
   locationsCollection: AngularFirestoreCollection<Location>;

  constructor(
    public loadingCtrl: LoadingController,
    private firebaseService: FirebaseService
  ) {}

  ngOnInit() {
    this.locations = this.firebaseService.getLocations();

  }

For template:

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

<ion-content>
    <ion-list>
      <ion-item *ngFor="let location of  ( locations | async)">
        <ion-label>{{location.title}}</ion-label>
      </ion-item>
    </ion-list>
</ion-content>

I’m using ionic version 5.4.9

I would suggest adding the following line to the compilerOptions of your tsconfig.json. It should guide you through how to fix this problem and protect you from similar bugs in the future:

"strictPropertyInitialization": true

I have tried that… still the same issue, no data, no error

also check XHR calls on the web developer console on the browser to see if there’s an error on your http calls to firebase

There are no errors their too…

If there are no errors and the http calls return a response with data, you have a lead to follow from there on…

I have a very hard time believing that, because you have not initialized either locations or locationsCollection.

1 Like

Actually, after signing out and creating a new account, it works fine… I don’t know why, though I would like to know, why? why does it not work on that single account

Hi Maina,
I have couple of questions after looking at your code. Please find them below.

import { Injectable } from '@angular/core';
import { AngularFirestore, AngularFirestoreCollection } from '@angular/fire/firestore';
import { AngularFireAuth } from '@angular/fire/auth';
import * as firebase from 'firebase';
import { Observable } from 'rxjs';
import { map } from 'rxjs/operators';

export interface Location {
  id: string;
    title: string;
    area: number;
    location: string;
    description: Text;
    image: string;
}

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

  private snapshotChangesSubscription: any;
  public currentUser: any;
  private user:any;
  locations: Observable<Location[]>;
  locationsCollection: AngularFirestoreCollection<Location>;

  constructor(
    public afs: AngularFirestore,
    public afAuth: AngularFireAuth
  ){
    this.afAuth.onAuthStateChanged(res => {
      if(res){
       this.user = res;
       console.log('User '+res.uid+' is logged in');
       this.locationsCollection = this.afs.collection<Location>
      //  ('people').doc(res.uid).collection('locations');
       (
         `people/${res.uid}/locations`,
         ref => ref.orderBy('timestamp')
       );

       this.locations = this.locationsCollection.snapshotChanges().pipe(
         map(actions =>{
           return actions.map(a => {
            // console.log('User '+res.uid+' is still logged in');
             const data = a.payload.doc.data();
             const id = a.payload.doc.id;
             return { id, ...data };
           });
          })
       );
      }
      });
  }

  getLocations():Observable<Locations[]>{
      return this.locations;
  }

When do you call your this.afAuth.onAuthStateChanged? You are only loading the locations if auth state has been changed. If not no locations are being fetched into the observable. That might be the reason why its working only if you logout and login or create an account. I would recommend you to separate your fetch call from your auth check function.

  1. Have you ever worked with ionic page life cycle? Do you know that ionic doesn’t destroy the pages it loaded like a normal angular application does. But it stacks them in cache for faster turn around. If you have to fetch data every time you hit a page i recommend you to call the your below code inside ionViewWillEnter() page hook. This link will help you get started with Ionic page life cycle.
ngOnInit() {
    this.locations = this.firebaseService.getLocations();

  }