You have unlimited access as a PRO member
You are receiving a free preview of 3 lessons
Your free preview as expired - please upgrade to PRO
Recent Posts
- Object Oriented Programming With TypeScript
- Angular Elements Advanced Techniques
- TypeScript - the Basics
- The Real State of JavaScript 2018
- Cloud Scheduler for Firebase Functions
- Testing Firestore Security Rules With the Emulator
- How to Use Git and Github
- Infinite Virtual Scroll With the Angular CDK
- Build a Group Chat With Firestore
- Async Await Pro Tips
Advanced Reactive Forms Techniques With Firestore
Episode 108 written by Jeff DelaneyHealth Check: This lesson was last reviewed on and tested with these packages:
- Angular v6.0.3
- RxJS v6.2
- AngularFire2 v5.0.0-rc.10
Find an issue? Let's fix it
Source code available to pro members. Learn more
Full source code for Advanced Reactive Forms Techniques With Firestore on Github
Forms are one of the most critical, yet most cumbersome aspects of app development. They require a ton of HTML markup and require complex validation rules for a good user experience. Almost all forms must be synced to a backend database, leaving us faced a state management conundrum that is not always easy to solve. In this lesson, my goal is to provide you with a reliable solution for syncing your frondend forms to any backend database.
Angular’s ReactiveFormsModule is basically a standalone state management system, while Firebase manages its own state under the hood. We want to combine these tools into a unified system by building a reusable directive that makes working with Firestore and Reactive Forms nearly automatic.
New to Reactive Forms? I highly recommend watching the [basics(lessons/basics-reactive-forms-in-angular/) video] before attempting this lesson.
Syncing Reactive Forms to a Backend
There are several different strategies one could employ to sync their reactive forms a backend database. In our case, we will use Cloud Firestore and AngularFire2. Here’s how the basic process will work from a high level.
- Preload existing data from the database into the form.
- Listen to changes in the reactive form value.
- Debounce for a few seconds.
- Write the changes to the database.
- Repeat steps 2 through 4.
Firestore Form Directive
An Angular Attribute Directive can be used to abstract away the backend database work, giving us reusable code for multiple forms.
ng g directive fire-form |
When we’re done, basic usage will look like this. Drop the directive into a form, point to a Firestore document and the rest is magic.
<form [formGroup]="yourForm" fireForm path="contacts"> |
The path
attribute represents the firestore document or collection were the data will be saved. When pointing to a collection, it will automatically create a new document. Otherwise, you can point directly to an existing document ID.
<form ... path="contacts/someExistingID"> |
fireform.directive.ts
There is quite a bit happening in this directive to manage the state between the reactive form and Firestore database. Let’s break down some of the key points.
The Output/EventEmitter properties are used to emit events about state changes to the parent component. We need to to let the parent know when the form is modified, synced, or throws a backend error. A TypeScript setter is used to emit an event and change the internal state value at the same time.
preloadData()
grabs the current data from the form. This is useful when your form can be edited after initial submission.
autoSave()
listens to the reactive form value and after a 2000ms debounce will write the form data to the database, as long as all validation rules pass.
@HostListener('ngSubmit')
intercepts the form submission and runs the update on the backend. This allows your user to perform a regular save by clicking a button (as opposed to waiting for an auto-save).
@Directive({ |
import { Directive, Input, Output, EventEmitter, HostListener, OnInit, OnDestroy } from '@angular/core'; |
Syncing your reactive forms to Firestore can now be accomplished with a single line of HTML <form [formGroup]="someForm" fireForm path="someCollection/someId">
. If you have any questions or feedback please leave a comment or drop me a line on Slack.