user938e3ef455
user938e3ef455

Reputation: 349

Cannot read property 'user' of undefined in Angular and Firebase Auth

Working with Firebase for the first time and trying to set up email and Google auth in an Angular (v5) app. Following a tutorial (https://angularfirebase.com/lessons/google-user-auth-with-firestore-custom-data/#Step-5-User-Profile), I get an error:

ERROR TypeError: Cannot read property 'user' of undefined

The error is coming from the template:

login.component.html

<div *ngIf="auth.user | async; then authenticated else guest">
  <!-- template will replace this div -->
</div>
<!-- User NOT logged in -->
<ng-template #guest>
  <h3>Howdy, GUEST</h3>
  <p>Login to get started...</p>

  <button (click)="auth.googleLogin()">
    <i class="fa fa-google"></i> Connect Google
  </button>
</ng-template>
<!-- User logged in -->
<ng-template #authenticated>
  <div *ngIf="auth.user | async as user">
    <h3>Howdy, {{ user.displayName }}</h3>
    <img  [src]="user.photoURL">
    <p>UID: {{ user.uid }}</p>
    <p>Favorite Color: {{ user?.favoriteColor }} </p>
    <button (click)="auth.signOut()">Logout</button>
  </div>
</ng-template>

login.component.ts

import {Component} from '@angular/core';
import {AuthService} from '../auth/auth.service';

@Component({
  selector: 'app-login',
  templateUrl: './login.component.html',
  styleUrls: ['./login.component.css']
})
export class LoginComponent {

  constructor(public authService: AuthService) {
  }
}

auth.service.ts

import {Injectable} from '@angular/core';
import {Router} from '@angular/router';
import * as firebase from 'firebase/app';
import {AngularFireAuth} from 'angularfire2/auth';
import {AngularFirestore, AngularFirestoreDocument} from 
'angularfire2/firestore';
import {Observable} from 'rxjs/Observable';
import 'rxjs/add/operator/switchMap'

interface User {
  uid: string;
  email: string;
  photoURL?: string;
  displayName?: string;
  favoriteColor?: string;
}

@Injectable()
export class AuthService {

  user: Observable<User>;

  constructor(private afAuth: AngularFireAuth,
              private afs: AngularFirestore,
              private router: Router) {
    //// Get auth data, then get firestore user document || null
    this.user = this.afAuth.authState
      .switchMap(user => {
        if (user) {
          return this.afs.doc<User>(`users/${user.uid}`).valueChanges()
        } else {
          return Observable.of(null)
        }
      })
  }
  googleLogin() {
    const provider = new firebase.auth.GoogleAuthProvider()
    return this.oAuthLogin(provider);
  }
  private oAuthLogin(provider) {
    return this.afAuth.auth.signInWithPopup(provider)
      .then((credential) => {
        this.updateUserData(credential.user)
      })
  }
  private updateUserData(user) {
    // Sets user data to firestore on login
    const userRef: AngularFirestoreDocument<any> = 
    this.afs.doc(`users/${user.uid}`);
    const data: User = {
      uid: user.uid,
      email: user.email,
      displayName: user.displayName,
      photoURL: user.photoURL
    };
    return userRef.set(data)
  }
  signOut() {
    this.afAuth.auth.signOut().then(() => {
      this.router.navigate(['/']);
    });
  }
}

This SO question seems similar but unsure how the answer would apply to my issue: firebase onAuth() throwing: TypeError cannot read property 'auth' of undefined and how to fix my problem.

Here's a screenshot of the error:

enter image description here

Upvotes: 2

Views: 3063

Answers (1)

user938e3ef455
user938e3ef455

Reputation: 349

Yurzui's solution above solved the issue.

I changed the constructor(public authService: AuthService) to constructor(public auth: AuthService).

Upvotes: 1

Related Questions