Getting started with AngularFire and Firebase
In this post we'll look at setting up a Firebase project and use AngularFire to interact with our Firestore database. We'll cover basic Create, Read, Update and Delete (CRUD) operations.
The repository below contains the demo application used to perform these operations, I recommend cloning/forking it in order to follow along https://github.com/tomeustace/angularfire-basics
Firebase Project Setup
Install Firebase npm install firebase
Create new project firebase init
So now we need to create our realtime database in firebase.
In the next screen you'll be asked to select a location, so choose whatever makes sense for you. Then you'll be directed to your newly minted database.
Next you will need to create an app to connect to you Firebase project. So go to the Project Settings and select Web icon for our app. This will walk you through some options for creating your app. Hosting is free so I'd recommend using it.
You'll be asked to install the firebase SDK and it will show you your custom firebase config. This config will be added to our Angular project when we do the AngularFire install below, so we can ignore it for now.
Then you'll install the firebase-tools npm install -g firebase-tools
I'll skip the actual deploy.
Angular App
Install Angular if not installed already npm install -g @angular/cli
Create a new Angular project ng new my-project
Add AngularFire using schematic ng add @angular/fire
The angular fire install will ask you a few questions about your setup. It will recognize and configure the firebase web app we created above. The main config we are interested in is Firestore, I also selected the hosting option here.
If you now look at your git diff
you'll see the changes the install has made to your Angular application.
Now you can run ng serve
and visit http://localhost:4200. If everything went to plan you should see the demo app running.
Interacting with Firestore using AngularFire
Below shows the demo app running next to to the Firestore database. I recommend running the app and your Firebase console view side by side as shown below, so you can see the results of operations. Of course, you could modify to show them in app.
All Operations Are Contained in the CollectionService, shown at bottom of this post. We'll take a look at each individual operation below.
Create Collection
Below is a simple example showing how to create a collection. If no documentName is provided it will create a document with an auto generated ID.
// collection.service.ts
createCollection(collectionName: string, documentName?: string) {
if (documentName) {
try {
this.afs
.collection(collectionName)
.doc(documentName)
.set({ name: 'my value' })
} catch(error) {
console.error('createCollection', error);
}
} else {
try {
this.afs
.collection(collectionName)
.doc()
.set({ name: 'my value' });
} catch(error) {
console.error('createCollection', error);
}
}
}
Get Collection
// collection.service.ts
getCollection(collectionName: string, documentName?: string) {
const collection = this.afs.collection(collectionName);
if (documentName) {
const docValue$: Observable<unknown> = collection.doc(documentName).valueChanges();
docValue$.subscribe((res) => {
console.log(`Document value changed ${collectionName}/${documentName}: ${res}`);
});
// will show the collection changes, modified, added, removed etc
const docSnapshot$: Observable<unknown> = collection.doc(documentName).snapshotChanges();
docSnapshot$.subscribe((res) => {
console.log(`Document snapshot changed ${collectionName}/${documentName}: ${res}`);
});
} else {
const value$: Observable<unknown[]> = collection.valueChanges();
value$.subscribe((res) => {
console.log(`Collection value changed ${collectionName}: ${res}`);
});
// will show the collection changes, modified, added, removed etc
const snapshot$: Observable<DocumentChangeAction<any>[]> =
collection.snapshotChanges();
snapshot$.subscribe((res) => {
console.log(`Collection snapshot changed ${collectionName}: ${res}`);
});
}
}
Update Collection
// collection.service.ts
updateDocument(collectionName: string, documentName: string, data: any) {
this.afs.collection(collectionName).doc(documentName).update(data);
}
Delete Document
Collection Service
The collection.service.ts contains all operations shown above.
import { Injectable } from '@angular/core';
import { AngularFirestore, DocumentChangeAction, } from '@angular/fire/compat/firestore';
import { Observable } from 'rxjs';
@Injectable()
export class CollectionService {
allCollections = false;
COLLECTION_LIST = 'collectionList';
constructor(private afs: AngularFirestore) {
if (!this.allCollections) {
this.createCollectionList();
}
}
/**
* @param collectionName
* @param documentName Optional
* Create a collection. If no documentName is provided a document
* will be created with auto generated id.
*/
createCollection(collectionName: string, documentName?: string) {
if (documentName) {
try {
this.afs
.collection(collectionName)
.doc(documentName)
.set({ name: 'my value' })
this.addCollectionToList(collectionName);
} catch(error) {
console.error('createCollection', error);
}
} else {
try {
this.afs
.collection(collectionName)
.doc()
.set({ name: 'my value' });
this.addCollectionToList(collectionName);
} catch(error) {
console.error('createCollection', error);
}
}
}
/**
* @param collectionName
* @param documentName Optional
* Shows how to subscribe to a collection or document.
* valueChanges() - listen to all documents in collection
* snapshotChanges() - listen to all documents in collection and their metadata, e.g. document ID
*/
getCollection(collectionName: string, documentName?: string) {
const collection = this.afs.collection(collectionName);
if (documentName) {
const docValue$: Observable<unknown> = collection.doc(documentName).valueChanges();
docValue$.subscribe((res) => {
console.log(`Document value changed ${collectionName}/${documentName}: ${res}`);
});
// will show the collection changes, modified, added, removed etc
const docSnapshot$: Observable<unknown> = collection.doc(documentName).snapshotChanges();
docSnapshot$.subscribe((res) => {
console.log(`Document snapshot changed ${collectionName}/${documentName}: ${res}`);
});
} else {
const value$: Observable<unknown[]> = collection.valueChanges();
value$.subscribe((res) => {
console.log(`Collection value changed ${collectionName}: ${res}`);
});
// will show the collection changes, modified, added, removed etc
const snapshot$: Observable<DocumentChangeAction<any>[]> =
collection.snapshotChanges();
snapshot$.subscribe((res) => {
console.log(`Collection snapshot changed ${collectionName}: ${res}`);
});
}
}
/**
* @param collectionName
* @param documentName
* Update data in document
*/
updateDocument(collectionName: string, documentName: string, data: any) {
this.afs.collection(collectionName).doc(documentName).update(data);
}
/**
* @param collectionName
* @param documentName
* Update data in document
* NOTE: Deleting a collection requires coordinating an unbounded number of individual
* delete requests. If you need to delete entire collections, do so only from a
* trusted server environment. While it is possible to delete a collection from a
* mobile/web client, doing so has negative security and performance implications.
*/
deleteDocument(collectionName: string, documentName: string) {
this.afs.collection(collectionName).doc(documentName).delete();
}
/**
* Create a collection list.
* This is for keeping track of all collections created.
*/
private createCollectionList() {
this.afs
.collection(this.COLLECTION_LIST)
.doc('list')
.set({})
.then(() => {
this.allCollections = true;
});
}
/**
* @param collectionName
* For each collection created a document with same name will be added
* to the collection list.
*/
private addCollectionToList(collectionName: string) {
this.afs
.collection(this.COLLECTION_LIST)
.doc(collectionName)
.set({ name: 'test' })
.then(() => {
this.allCollections = true;
});
}
/**
* Get all available collections.
*/
getAllCollections() {
this.afs
.collection(this.COLLECTION_LIST)
.valueChanges()
.subscribe((res) => {
console.log('All collections', res);
});
}
}
Wrap Up
This has been an basic introduction to getting up and running with Firebase and AngularFire.