Cloud Firestore is hot new document database in the cloud for mobile and web app for saving your data to the cloud.I want to create a little web app where we can store an Inspirational quote.My web app here consists of a text field, where I can enter my inspirational quote.We’ve got a save button, where we’re going to save whatever inspiring message our user has entered to the cloud.Later on, we’ll load whatever data our user has saved to the cloud and display it at H1
tag, so we can see the latest inspirational quote that we’ve entered.
Getting Started with Cloud Firestore on Web
Let’s take a look at what I’ve got set up.So here’s index.html
page, where I’ve got all my elements created.I’m loading the Firebase library.
<!DOCTYPE html> <html> <head> <title>Firestore</title> <script src="https://www.gstatic.com/firebasejs/4.6.0/firebase.js"></script> <script src="https://www.gstatic.com/firebasejs/4.6.0/firebase-firestore.js"></script> </head> <body> <h1 id="lblQuote"></h1> <input type="text" id="txtQuote" /> <button id="saveButton">SAVE</button> <button id="loadButton">LOAD</button> <script src="app.js"></script> </body> </html>
Then, over here is my app.js
file, where I’m configuring my Firebase project with the values that I got from the Firebase Console.
var config = { apiKey: "AIzaSyApREa6-Q8hMQRRbEq6_jsjJsjwiowwiwX08", authDomain: "web-jnd.firebaseapp.com", databaseURL: "https://web-jnd.firebaseio.com", projectId: "web-jnd", storageBucket: "", messagingSenderId: "571823669" }; firebase.initializeApp(config);
I’ve already created IDs for my header, my text field, and my button.So first things I’m going to jump into my app.js
file and create a few variables to hold references to these elements.I’ll do that just by calling querySelector
.
.... const outputHeader=document.querySelector("#lblQuote"); const inputTextField=document.querySelector("#txtQuote"); const saveButton=document.querySelector("#saveButton"); const loadButton=document.querySelector("#loadButton"); ....
Next up, I’m going to create a click event listener for the save button.Now I’ll grab the text that I want to save from my inputTextField.value
and let’s log it to confirm.Let’s log it to confirm we have some actual data.
saveButton.addEventListener("click",function(){ const textToSave=inputTextField.value; console.log("Quotes "+textToSave); ... });
Initialize Cloud Firestore
Initialize Cloud Firestore through Firebase.
... var firestore = firebase.firestore(); ...
Now, I just need to save it to the cloud and to do that, I need to specify in which document
I want to put this data.We do that through something known as a document
reference.
.... const docRef = firestore.doc("samples/quote"); ....
I’ll be using the same reference a few times throughout this project.So I’m actually going to define it top of the script. you’re always going to be alternating between collections and documents. Now, I’ve specified my document, let’s go back to my event listener, where I’m going to call
set
on this document
reference. Now, this will take in a JavaScript object to represent the data that we want to save for this document inspirationalQuote
as textToSave that’s all I really need.This will replace my current document if it exists, and it will create it if it doesn’t.It also conveniently creates the samples collection too.So I don’t need to worry about whether or not that exists.
saveButton.addEventListener("click",function(){ const textToSave=inputTextField.value; console.log("Quotes "+textToSave); docRef.set({ inspirationalQuote:textToSave }).then(function(){ console.log("Quote Save"); }).catch(function(error){ console.log("Got an error: ",error); }); });
Now, the set
function, as with most Firestore functions, returns a promise, which means it’s pretty easy to note when this call is complete.so I’ll attach a then
callback at the end here, and print out a little success message, and come to think of it, I’ll add a catch
here to print out any errors.
Error: Missing or insufficient permissions.
Cloud Firestore implementation contains a set of security rules that determine whether or not a certain action is permitted.The proper solution would be to add some sign-in using Firebase Auth and then create some proper, well thought out security rules, base on what information. I’m willing to share to each individual user.So I’m going to do a bit of a hack here and make anything in my samples collection open to the public. So let’s head on over to the Firebase Console, make sure you’ve got your project selected, and I’m in the database section and then here, I’ll make sure cloud Firestore is selected for my list of database options.And then, I will click on the rule tab.Next, I’m going to add this here to allow reading and writing that’s part of my samples collection. Time to load up our page and give this a try.
I can verify this by going back to the Firebase console.We’ll select the Data tab to view our data.We’ll select our samples collection and sure enough, looks like we’ve saved our thought.
Get Data with Cloud Firestore
It’s great that we can see this data in the Firebase Console, we need to show this important information to our users too.So next up, let’s learn how to grab this data from the cloud and put it into our H1
tag. Now, like the Realtime Database, Cloud FIrestore lets me listen to changes in the database and update my app in real-time. Now, getting this function to work is actually quite easy.I’m going to take that same document
reference we created earlier and, instead of calling set
on it, I’m just going to call get
instead.This returns a promise.So I can attach a then callback to it, which will run when this get
call is complete.Note that, this takes in a documented snapshot that I’m just calling doc here.A document snapshot is basically an object that represents your document. You can find out its ID, read some metadata about it, make sure the underlying document it represents really exists, and more importantly, grab the data that it contains by calling data on it.So we’ll see if this snapshot exists and if it does, we will call data to extract the contents of that document as an object.Then, I can set the text of our big output header to my data.inspirationalQuote
.And as long as we’re here, let’s add a catch
at the end to catch any error that might come up.
loadButton.addEventListener("click",function(){ docRef.get().then(function(doc){ if(doc && doc.exists){ const myQuote=doc.data(); outputHeader.innerText="My Inspirational Quote: "+myQuote.inspirationalQuote; } }).catch(function(error){ console.log("Got an error: ",error); }); });
So let’s run this.I can still save our latest quotes to the world. Now, I’ll click the Load button to load it and there it is on our page.
Get Realtime Updates with Cloud Firestore
So this is great.We’ve got our data successfully saved and loaded from cloud Firestore.But what if you are interested in getting your data in real time? What if this explicit fetching seems quaint and old-fashioned to you? Well, let’s show you how to get your data in real-time as well. Basically, the process is going to work nearly the same.Let’s create a function called getRealtimeUpdates
and in there,I’m going to bring up my document
reference.But then instead of calling get
, I’m going to use the onSnapshot
.This will fire the first time I call it.But then, it will also fire any time thereafter when my data changes.Now, this call takes in a callback function, which accepts the document snapshot as an argument, essentially just like my get
call.So in fact, I’m just to copy the exact same code for my get
call into here to update my label
.Well, that’s it.We’ll call getRealtimeUpdates
at the bottom of our script.That should be all we need.Here, let’s reload the page.
getRealTimeUpdate=function(){ docRef.onSnapshot(function(doc){ if(doc && doc.exists){ const myQuote=doc.data(); console.log("Check out this document I received ",doc); outputHeader.innerText="My Inspirational Quote: "+myQuote.inspirationalQuote; } }); } getRealTimeUpdate();
Now you can see that my text automatically gets updated with current save Quote the value that was in the cloud previously.I hit save and you can see that my label gets updated automatically without my having to even touch that load button, that was fast.In fact, maybe too fast, right? It looks like my label got updated before that data was even saved.How’d that happen? Well, what’s happening is that cloud Firestore is making my app run as speedy as possible, by notifying me of changes as if they had happened on the server.But in the meantime, It’s still going ahead and updating that data remotely in the background.
Thanks. Very clean and goog code for beginners.