Angular together with Firebase makes a potent combination. Jamie Perkins' presentation shows how to create a production-ready app using these tools in only a half hour. This project only scratches the surface of Firebase, but demonstrates:
- Setting up authentication
- Make an auth guard to protect routes
- Make use of avatars
- Read and write Firestore data
And as a bonus, you'll get to know Angular google maps. Later in your project, you can take advantage of cloud storage, cloud functions, and everything else Firebase has to offer.
If you're wondering what a real-world AngularFire app looks like, check out Podmap, an open-source app I built to map the world's podcasts.
To run this project locally, you'll need to create a new Firebase project and get a Google maps API key.
Create an environment.ts file from the provided sample file and replace the keys.
Build and run locally:
$ ng s
First, globally install firebase tools:
$ npm i -g firebase-tools
Login to firebase:
$ firebase login
Build the app for prod so you can test deployment:
$ ng build --prod
You can init and re-init any time. The init
command makes it easy to configure firebase.
- For now, only choose hosting when prompted for what to configure locally.
- Configure as an SPA? - Yes.
- For serve folder, choose
dist/project-name
$ firebase init
Deploy. Your app will be instantly hosted and accessible at the provided url.
$ firebase deploy
Here are some code snippets that took me a bit of trial and error. They aren't used in the project so I included them here for reference using a generic model "Entity":
getOrElse(entity: Entity): Promise<Entity | any> {
return new Promise((resolve, reject) => {
this.afs.doc<Entity>(docPath).valueChanges().pipe(
first()
).toPromise()
.then(result => {
if (result === undefined) {
// not found - this is the "else"
// do stuff here or just reject
reject('document does not exist');
} else {
resolve(result);
}
})
.catch((err) => reject(err));
}
}
addOrUpdate(entity: Entity): Promise<any> {
return new Promise((resolve, reject) => {
const docPath = `entities/${entity.id}`;
// try to update first
this.afs.doc(docPath).update(entity)
.then(() => resolve())
.catch(() => {
// doc doesn't exist, add
this.afs.doc(docPath).set(entity)
.then(() => resolve())
.catch(err => reject(err));
});
});
}