Implementing Firestore in Angular

This guide delves into the powerful combination of Firestore and Angular, showcasing how to leverage Google's realtime database service with one of the most popular front-end frameworks. By the end of this series, you'll be equipped with the knowledge to build seamless, realtime web applications efficiently.


Introduction to Firebase and Firestore

Firebase is a mobile platform by Google designed to help developers build high-quality applications swiftly. It offers a range of services such as authentication, APIs, and databases, all of which can be managed seamlessly. Firestore, a recent addition, provides a more advanced data model compared to the Realtime Database, featuring sophisticated querying capabilities and superior scalability.


Comparing Cloud Firestore and Realtime Database

Introduced on October 3rd, 2017, Cloud Firestore offers an enhanced data model, improved queries, and better security compared to Firebase's Realtime Database. Here are some key differences:


  • Firestore allows for more complex queries, including chain filtering and sorting.
  • It provides offline support for web applications as well, whereas Realtime Database supports only mobile clients for iOS and Android.
  • Firestore features a different pricing model, charging for reads, writes, deletes, storage, and network bandwidth usage.


Pricing Structure of Firestore

Firestore's pricing model is mainly based on the number of reads, writes, and deletes performed in the database, along with storage and network bandwidth consumption. This is different from Realtime Database, which charges primarily for bandwidth and storage.


Details of Firestore Charges:
  • Reads: Charged each time a document is retrieved, including when listening to query results that update frequently.
  • Writes: Any additions, updates, or deletions of documents are counted as writes.
  • Storage: Charges are based on the total amount of data stored in Firestore, including metadata and indexes.
  • Bandwidth: Network bandwidth usage is also billed, but at a lower rate than the Realtime Database.


Firestore vs. MongoDB

Both Firestore and MongoDB are popular NoSQL databases, but there are notable differences:


  • Scalability: While MongoDB offers horizontal scaling, Firestore provides automatic scaling.
  • Real-time Updates: Firestore shines with its native support for real-time data synchronization, making it ideal for apps that require real-time updates.
  • Server-Side Operations: With Firestore, many backend operations can be handled within the Firebase ecosystem, whereas MongoDB often requires additional backend setup.


Getting Started with Firestore in an Angular Project

This section will walk you through setting up a Cloud Firestore project with Angular, including the necessary modules and authentication services. Let's dive in!


Creating a Cloud Firestore Project

  1. Open the Firebase Console and create a new project.
  2. In the "Database" section, click on "Get Started" for Cloud Firestore.
  3. Select a starting mode for your Cloud Firestore Security Rules:some text
    • Test mode: Ideal for initial development, but remember to set more stringent rules for production.
    • Locked mode: Denies all reads and writes from clients, allowing access only through your authenticated servers.
  4. Click "Enable."
  5. Navigate to the "Authentication" section, then to "Providers," and enable Google authentication.

Installing Angular Packages

For integrating Firestore with Angular, you'll need to install AngularFire2, the official Angular library for Firebase, as well as the Firebase JS SDK and RxJS for complex queries.


npm install firebase @angular/fire rxjs --save

Adding Firebase Configuration

Next, add your Firebase configuration to the environments file. Open /src/environments/environment.ts and add the following configuration:


export const environment = {
production: false,
firebase: {
apiKey: '<your-key>',
authDomain: '<your-project-authdomain>',
databaseURL: '<your-database-URL>',
projectId: '<your-project-id>',
storageBucket: '<your-storage-bucket>',
messagingSenderId: '<your-messaging-sender-id>'
}
};

Setting Up Angular Modules

Now, open /src/app/app.module.ts, inject Firebase providers, and specify your Firebase configuration:


import { BrowserModule } from '@angular/platform-browser';
import { NgModule } from '@angular/core';
import { AppComponent } from './app.component';
import { AngularFireModule } from '@angular/fire';
import { AngularFirestoreModule } from '@angular/fire/firestore';
import { AngularFireAuthModule } from '@angular/fire/auth';
import { environment } from '../environments/environment';

@NgModule({
imports: [
BrowserModule,
AngularFireModule.initializeApp(environment.firebase, 'my-app-name'), // imports firebase/app needed for everything
AngularFirestoreModule, // imports firebase/firestore, only needed for database features
AngularFireAuthModule, // imports firebase/auth, only needed for auth features
],
declarations: [ AppComponent ],
bootstrap: [ AppComponent ]
})
export class AppModule {}

Creating an Authentication Service

Thanks to Firebase, integrating authentication providers is straightforward. Here's how to implement Google OAuth:


import { AngularFireAuth } from '@angular/fire/auth';
import * as firebase from 'firebase/app';

constructor(
private angularFireAuth: AngularFireAuth
) { }

login() {
const authProvider = new firebase.auth.GoogleAuthProvider();
this.angularFireAuth.auth.signInWithRedirect(authProvider);
}

logout() {
this.angularFireAuth.auth.signOut();
}

Handling User Data

To display user data, leverage the authState observer from AngularFireAuth:


import { Store, select } from '@ngrx/store';
import { ofType, Actions } from '@ngrx/effects';
import { map, switchMap, catchError } from 'rxjs/operators';
import { of } from 'rxjs';
import * as fromAuth from './auth.reducer';
import * as authActions from './auth.actions';

@Effect()
authenticateUser$ = this.actions$
.pipe(
ofType(authActions.AUTHENTICATE_USER),
switchMap(() => {
return this.angularFireAuth.authState.pipe(
map((identity: firebase.User) => {
return identity
? new authActions.AuthenticateUserSuccess(identity)
: new authActions.AuthenticateUserFail('User Not logged In.');
}),
catchError(error => of(new authActions.AuthenticateUserFail(error)))
);
})
);

Remember, when a user signs in through a federated identity provider like Google or Facebook, a new profile is created in your app. Any changes to the user's profile on Google or Facebook will not automatically be reflected in your Firestore data.


Next Steps

This is just the beginning of our deep dive into integrating Firestore with Angular. In the next parts of this guide, you'll learn how to create both basic and advanced queries, manage data effectively, and implement realtime updates. Stay tuned for further detailed instructions on these topics.


Be sure to check out the Firebase Documentation for more insights and detailed information.