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
Oldest comments (18)
Exellent resource. I am currently working on a tutorial using Angular 12 with firebase 9.
Very good reference and crisp representation of the required imports & implementation without any fluff. Thank you.
Thank you. This has been very useful today. I'm starting a new project and want to use the new APIs but the lack of documentation is infuriating.
I have been scouring the internet for 24 hours looking for an example of how to implement the new AngularFire Auth API!! thank you!!!
great article
do u have anywhare u go in details about the use of collections search where, pagination... in angular 12+ firestore 9 (angularfire 7)
Yes, just look at the
where
examples above. Pagination will uselimit()
andorderBy()
as usual, just import them.Thanks so much for this! You wrote "I may update this with more items..." and I cant' wait. We need articles like this, bc the official @angular/angularfire documentation is awful.
Is there something you specifically need? If so I can add it!
Nothing specific, just more of that juicy stuff - the more the better.
You saved a life today. Thank you
Type casting is not working here:
Yes, Angular Firebase is definitely not perfected code with Firebase 9. You can get around that with:
When adding a new document to firestore, how do we tell it to auto generate id? If I don't put id in doc() it gives me an error.
Thanks. I was loosing my sanity over the official docs.
Great reference, thank you. Turns out when you step away from AngularFire for a year+ several things change lol.
HI: This code doesn't work with 7.4.1 and angular 14.
this.user$ = user(auth).pipe(
switchMap((user: User | null) =>
user
? docData(doc(this.afs, 'users', user.uid))
as Observable
: of(null)
)
);
Help... :(
Read my updated article on this - this article is out-of-date - code.build/p/angular-todo-app-with... - make sure you're using
importProvidersFrom()