Angular 12 with Firebase 9

jdgamble555

Jonathan Gamble

Posted on September 6, 2021

Angular 12 with Firebase 9

Update 3/7/24

For a modern Angular Firebase App, see my latest post:
https://code.build/p/angular-todo-app-with-firebase-fmLJ37


Original Post


Quick Reference

Angular's Docs have not been updated fully yet, so I made a quick reference.

app.module.ts - Imports

import { provideFirebaseApp, initializeApp } 
from '@angular/fire/app';
import { getAuth, provideAuth } 
from '@angular/fire/auth';
import { getFirestore, provideFirestore } 
from '@angular/fire/firestore';
import { getStorage, provideStorage } 
from '@angular/fire/storage';
import {
  getAnalytics,
  provideAnalytics,
  ScreenTrackingService,
  UserTrackingService
} from '@angular/fire/analytics';
...

@NgModule({
  declarations: [],
  imports: [
    provideAnalytics(() => getAnalytics()),
    provideFirebaseApp(() => initializeApp(environment.firebase)),
    provideFirestore(() => getFirestore()),
    provideAuth(() => getAuth()),
    provideStorage(() => getStorage())
    ...
  ],
  providers: [
    ScreenTrackingService,
    UserTrackingService
  ],
})
Enter fullscreen mode Exit fullscreen mode

Note: For Angular Universal SSR, you may have problems with provideAnalytics(). Either use the old version, or only load it on the server version. I could not get it to work correctly in regular Angular, but they may have fixed the code in a newer version.

import

import {
  collection,
  doc,
  docData,
  DocumentReference,
  CollectionReference,
  Firestore,
  onSnapshot,
  query,
  where,
  Unsubscribe,
  Query,
  DocumentData,
  collectionData,
  collectionChanges,
  docSnapshots,
  ...
} from '@angular/fire/firestore';
Enter fullscreen mode Exit fullscreen mode

constructor

constructor(
  private afs: Firestore
) { }
Enter fullscreen mode Exit fullscreen mode

Documents

valueChanges()

docData<Post>(
  doc(this.afs, 'posts', id)
);
Enter fullscreen mode Exit fullscreen mode

snapShotChanges()

docSnapshots<Post>(
  doc(this.afs, `posts/${id}`)
);
Enter fullscreen mode Exit fullscreen mode

Collections

valueChanges()

collectionData<Post>(
  query<Post>(
    collection(this.afs, 'posts') as CollectionReference<Post>,
    where('published', '==', true)
  ), { idField: 'id' }
);
Enter fullscreen mode Exit fullscreen mode

snapShotChanges()

collectionChanges<Post>(
  query<Post>(
    collection(this.afs, 'posts') as CollectionReference<Post>,
    where('published', '==', true)
  )
);
Enter fullscreen mode Exit fullscreen mode

createId()

doc(collection(this.afs, 'id')).id;
Enter fullscreen mode Exit fullscreen mode

Auth

imports

import {
  Auth,
  signOut,
  signInWithPopup,
  user,
  signInWithEmailAndPassword,
  createUserWithEmailAndPassword,
  updateProfile,
  sendEmailVerification,
  sendPasswordResetEmail,
  getAdditionalUserInfo,
  OAuthProvider,
  linkWithPopup,
  unlink,
  updateEmail,
  updatePassword,
  User,
  reauthenticateWithPopup,
  authState,
  onAuthStateChanged
  ...
} from '@angular/fire/auth';
Enter fullscreen mode Exit fullscreen mode

Code

user$: Observable<User | null>;

constructor(private auth: Auth) {

  // user observable, not user doc
  this.user$ = user(auth);

  // or use this version...
  this.user$ = authState(auth);

  // or use this version...
  this.user$ = new Observable((observer: any) =>
    onAuthStateChanged(auth, observer)
  );

  // or pipe user doc, Profile interface
  // returns user doc, not User type
  // here this.user$: Observable<Profile | null>;
  this.user$ = user(auth).pipe(
      switchMap((user: User | null) =>
        user
          ? docData(doc(this.afs, 'users', user.uid))
            as Observable<Profile>
          : of(null)
      )
    );

}

async getUser(): Promise<User | null> {
  return await this.user$.pipe(take(1)).toPromise();
}

...

async emailLogin(email: string, password: string)
: Promise<any> {
  return await signInWithEmailAndPassword(this.auth, email, password);
}

async emailSignUp(email: string, password: string)
: Promise<void> {

  const credential = await createUserWithEmailAndPassword(
    this.auth,
    email,
    password
  );
  await updateProfile(
    credential.user, { displayName: credential.user.displayName }
  );
  await sendEmailVerification(credential.user);

  // create user in db
  ...
}

async resetPassword(email: string): Promise<any> {

  // sends reset password email
  await sendPasswordResetEmail(this.auth, email);
  ...
}

async oAuthLogin(p: string): Promise<void> {

  // get provider, sign in
  const provider = new OAuthProvider(p);
  const credential = await signInWithPopup(this.auth, provider);
  const additionalInfo = getAdditionalUserInfo(credential);

  // create user in db
  if (additionalInfo?.isNewUser) {
    ...
  }
}
Enter fullscreen mode Exit fullscreen mode

Storage

Import

import {
  Storage,
  ref,
  deleteObject,
  uploadBytes,
  uploadString,
  uploadBytesResumable,
  percentage,
  getDownloadURL,
  ...
} from '@angular/fire/storage';
Enter fullscreen mode Exit fullscreen mode

Code

uploadPercent: Observable<number>;

constructor(private storage: Storage) { }

async upload(
  folder: string,
  name: string,
  file: File | null
): Promise<string> {

  const ext = file!.name.split('.').pop();
  const path = `${folder}/${name}.${ext}`; {

  if (file) {
    try {
      const storageRef = ref(this.storage, path);
      const task = uploadBytesResumable(storageRef, file);
      this.uploadPercent = percentage(task);
      await task;
      const url = await getDownloadURL(storageRef);
    } catch(e: any) {
      console.error(e);
    }   
  } else {
    // handle invalid file
  }
  return url;
}
Enter fullscreen mode Exit fullscreen mode

I may update this with more items, but I wanted to be particular to Angular and not get into the general Firebase 9 updates. I didn't want to show every possible example, but you start to see the patterns.

J

💖 💪 🙅 🚩
jdgamble555
Jonathan Gamble

Posted on September 6, 2021

Join Our Newsletter. No Spam, Only the good stuff.

Sign up to receive the latest update from our blog.

Related

Angular 12 with Firebase 9
angular Angular 12 with Firebase 9

September 6, 2021