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
Top comments (19)
Type casting is not working here:
Yes, Angular Firebase is definitely not perfected code with Firebase 9. You can get around that with:
hello, I'm facing an error with firebase auth / angular. I well configure my Angular app module with provideAuth(() => getAuth()) under providers sections but even when including no code related to Auth inside my app, I get
SyntaxError: Unexpected number in JSON at position 2 (line 1 column 3)
related with file_/scs/abc-static/_/js/k=gapi.lb.fr.MtA0XocprA0.O/m=gapi_iframes/rt=j/sv=1/d=1/ed=1/am=AAAg/rs=AHpOoo90Qw_OxY6asHlYoeK8rr6SbH-ghg
firebase did work with firestore
provideFirestore(() => getFirestore())
but not with Auth.I don't know at all what to do since I execute no code yet linked with auth inside my components...
Can someone help?
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()
I have been scouring the internet for 24 hours looking for an example of how to implement the new AngularFire Auth API!! 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.
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)
)
);
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.
Thanks. I was loosing my sanity over the official docs.
Very good reference and crisp representation of the required imports & implementation without any fluff. 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.