Magnus
Magnus

Reputation: 1075

Angular cannot subscribe to firebase list observable

I have an angular app using firebase. The app has two services. The first one is for authentication. It has an observable with the current authenticated user.

import { AngularFireAuth } from 'angularfire2/auth';
import { Injectable } from '@angular/core';
import * as firebase from 'firebase';
import { Observable } from 'rxjs/Observable';

@Injectable()
export class AuthService {

 user$: Observable<firebase.User>;

 constructor(private afAuth: AngularFireAuth) {
   this.user$ = afAuth.authState;
 }

 getUser() {
   console.log(this.user$);
 }

 loginWithEmailAndPassword(email, password) {
   this.afAuth.auth.signInWithEmailAndPassword(email, password);
 }

 loginWithGoogle() {
   this.afAuth.auth.signInWithRedirect(new firebase.auth.GoogleAuthProvider());
 }

 logOut() {
   this.afAuth.auth.signOut();
 }

}

The second services contains myFokos observable that subscribes to my firebsae realtime database list.

import { Observable } from 'rxjs/Observable';
import { AuthService } from './auth.service';
import { Injectable } from '@angular/core';
import { AngularFireDatabase } from 'angularfire2/database';

@Injectable()
export class MyListService {

 myFokos: Observable<any[]>;

 constructor(auth: AuthService, database: AngularFireDatabase) {
   auth.user$.subscribe(user => {
     console.log('User is logged in. UID: ' + user.uid);
     this.myFokos = database.list('users/' + user.uid + '/glossaries').snapshotChanges();
   });
 }

}

Then I try to access myFokos observable from MyListService.

import { AuthService } from './../../services/auth.service';
import { MyListService } from './../../services/my-list.service';
import { Component, OnInit } from '@angular/core';

@Component({
 selector: 'app-my-fokos',
 templateUrl: './my-fokos.component.html',
 styleUrls: ['./my-fokos.component.css']
})
export class MyFokosComponent implements OnInit {

 constructor(public myListService: MyListService, public auth: AuthServ

ice) { }

     ngOnInit() {
       this.myListService.myFokos.subscribe(x => {
    console.log(x);
  });
 }

}

When I do this, I get an error in the console:

MyFokosComponent_Host.ngfactory.js? [sm]:1 ERROR TypeError: Cannot read property 'subscribe' of undefined
   at MyFokosComponent.ngOnInit (my-fokos.component.ts:15)
   at checkAndUpdateDirectiveInline (core.js:12364)
   at checkAndUpdateNodeInline (core.js:13888)
   at checkAndUpdateNode (core.js:13831)
   at debugCheckAndUpdateNode (core.js:14724)
   at debugCheckDirectivesFn (core.js:14665)
   at Object.eval [as updateDirectives] (MyFokosComponent_Host.ngfactory.js? [sm]:1)
   at Object.debugUpdateDirectives [as updateDirectives] (core.js:14650)
   at checkAndUpdateView (core.js:13797)
   at callViewAction (core.js:14148)

I think the problem is that myFokos observable is undefined until MyListService gets the user$ observable from AuthService, but I do not how I can fix it. I have tried to combine user$ and myFokos and then subscribe to that in the component, but that did not work.

I do not get the error when I navigate to another route and back. I can also get the data from HTML like this:

*ngFor="let foko of myListService.myFokos | async"

This question is not a duplicate of this question because the answer was to get the data from the database in the component instead. I do not want to this in my app because I am using the data from myFokos observable in multiple components.

Upvotes: 2

Views: 2880

Answers (1)

Sondre S&#248;rbye
Sondre S&#248;rbye

Reputation: 549

Your code is not realy pure async code:

constructor(auth: AuthService, database: AngularFireDatabase) {
  auth.user$.subscribe(user => {
    console.log('User is logged in. UID: ' + user.uid);
    this.myFokos = database.list('users/' + user.uid + '/glossaries').snapshotChanges();
  });
}

This is much easier

constructor(auth: AuthService, database: AngularFireDatabase) {
  this.myFokos$=auth.user$.switchMap(user => {
    console.log('User is logged in. UID: ' + user.uid);
   return database.list('users/' + user.uid + '/glossaries').snapshotChanges();
  });
}

Upvotes: 1

Related Questions