2
votes

Pls help me i am new in angular6 firebase programing. I have good working firebase auth system with email and password. But from registration i can only get uid and email when i store User in database. I red about updateProfile but dont know how to implement in my code. I am using "@angular/fire": "^5.0.0", "firebase": "^5.5.1", so i am asking is this version good or i need to change. Back to question: Service:

 import { Injectable } from "@angular/core";
    import { AngularFireAuth } from "@angular/fire/auth";
    import {
      AngularFirestore,
      AngularFirestoreCollection,
      AngularFirestoreDocument
    } from "@angular/fire/firestore";
    import { Observable } from "rxjs";
    import "rxjs/add/operator/map";

    @Injectable()
    export class AuthService {
      constructor(private afAuth: AngularFireAuth, private db: AngularFirestore) {
        // this.afAuth.authState.subscribe(auth => console.log(auth));
      }

      login(email: string, password: string) {
        return new Promise((resolove, reject) => {
          this.afAuth.auth
            .signInWithEmailAndPassword(email, password)
            .then(userData => resolove(userData), err => reject(err));
        });
      }
      getAuth() {
        return this.afAuth.authState.map(auth => auth);
      }
      logout() {
        this.afAuth.auth.signOut();
      }
      register(email: string, password: string) {
        return new Promise((resolove, reject) => {
          this.afAuth.auth
            .createUserWithEmailAndPassword(email, password)
            .then(userData => resolove(userData), err => reject(err));
        });
      }
    }

Component

import { Component, OnInit } from "@angular/core";
import { AuthService } from "../../service/auth.service";
import { Router } from "@angular/router";

@Component({
  selector: "app-register",
  templateUrl: "./register.component.html",
  styleUrls: ["./register.component.css"]
})
export class RegisterComponent implements OnInit {
  email: string;
  password: string;
  constructor(private authService: AuthService, private router: Router) {}

  ngOnInit() {}

  onSubmit() {
    this.authService
      .register(this.email, this.password)
      .then(res => {
        this.router.navigate(["/"]);
      })
      .catch(err => console.log(err.message));
  }
}

My goal is to have displayName and skill as property of User in database. After registration with my code displayName is null. So my question is how to store displayName in database? Ty Viktor.

1
Welcome to StackOverflow. I'm not sure what's your question.Eliya Cohen
I am using firebase email and password authentication. And it works. But i want to store displayName prop in database too. For example i want to say Hello {{ user.displayName }}. But i cant cuz i dont know how to store it in database. Atm displayName is null.Viktor Molnar
Are you using firestore or real-time database?Eliya Cohen
Cloud Firestore.Viktor Molnar

1 Answers

1
votes

Welcome to StackOverflow.

The reason displayName is null, is because it's null by default (unless you're logging in from a social network such as Facebook and Google). What you should consider doing, is:

  • On each registration, create a new document inside users collection (name it to whatever you want).
  • On each login, update the existing document of the user (you don't have to, but sometimes it's useful).
  • Get the user document according to the currently authenticated user.

Let's start with the registration:

You have multiple sign-in methods, but I'll explain to you how it's done via Email/Password.

So first, we need to create the method register that accepts the email and password parameters. I see that you've already created the method, but you should know that you don't need to scope createUserWithEmailAndPassword inside a promise since it's already a promise. After the user registers, we'll add his data to our collection:

register(email: string, password: string) {
  this.afAuth.auth.createUserWithEmailAndPassword(email, password)
    .then(userCredential => this.upsertUserData(userCredential))
    .catch(error => this.handleAuthError(error);
}

private upsertUserData(userCredential: firebase.auth.UserCredential) {
  // Upsert = Update/Insert.
  return this.afs.doc(`users/${userCredential.uid}`).update({
    email: userCredential.email
  });
}

private handleAuthError(error) {
  console.error(error)
}

As you can see, I created additional two methods, to make the method register more clean and readable.

Now that we have the registration done, let's make the login method, which is almost the same:

login(email: string, password: string) {
  this.afAuth.signInWithEmailAndPassword(email, password)
    .then(userCredential => this.upsertUserData(userCredential))
    .catch(error = > this.handleAuthError(error));
}

After we did registration and login to the app, we want to get the data of the user so that we can do it like so:

export class AuthService {

...

user$: Observable<{displayName: string, email: string}> = this.afAuth.authState.pipe(
  switchMap(user => Boolean(user) ? this.afs.doc(`users/${user.id}`).valueChanges() : of(null))
);

...
}

To put it simply - this.afAuth.authState will emit an object if the user is logged in. If the user is not logged in, a null will be returned. user$ will return the document data of the user if the user is logged in. If the user doesn't exist (i.e., authState = null), a null will be returned.