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
],
})
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';
constructor
constructor(
private afs: Firestore
) { }
Documents
valueChanges()
docData<Post>(
doc(this.afs, 'posts', id)
);
snapShotChanges()
docSnapshots<Post>(
doc(this.afs, `posts/${id}`)
);
Collections
valueChanges()
collectionData<Post>(
query<Post>(
collection(this.afs, 'posts') as CollectionReference<Post>,
where('published', '==', true)
), { idField: 'id' }
);
snapShotChanges()
collectionChanges<Post>(
query<Post>(
collection(this.afs, 'posts') as CollectionReference<Post>,
where('published', '==', true)
)
);
createId()
doc(collection(this.afs, 'id')).id;
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';
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) {
...
}
}
Storage
Import
import {
Storage,
ref,
deleteObject,
uploadBytes,
uploadString,
uploadBytesResumable,
percentage,
getDownloadURL,
...
} from '@angular/fire/storage';
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;
}
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.
For that see Code.Build.
Or Firebase 9 Official Docs
Here is also an official angularfire sample project
J