In this video, we are going to walk through setting up a Firestore Database in a StencilJS and Ionic application. I released a video last week where we talked about setting up Firebase authentication in an Ionic and StencilJS project. So, this is going to pick up exactly where that left off. If you haven’t already been through that video or you don’t already know how to set up the Firebase SDK and get some authentication working you might want to go look at that video first and then come back to this one now.
The main focus of this video is taking what we have so far and then adding Firestore to that. We are setting up the database in the Firebase console here and then also doing what we need to do in our code to make that work. If you’ve completed the last tutorial you should have access to a Firebase project like this one. It should have an authentication setup for anonymous users. It doesn’t have to be anonymous you can use something else if you like.
What we need to do at this point is coming to our console again for the project and go to the Database section. It’s here that we’re going to set up our Firestore database. You’ll find a few different things on this Database page and some information but the main thing is that we have cloud Firestore at the top of the page or you can also choose to set up the old Real-time Firebase database.
There’s content out there already from people who can explain the difference between Firestore and the Real-time Firebase database better than I can. So, if you want to know what the difference is I’d recommend going and finding a video like that. The main point is that for most people it’s probably Firestore that you want to be using. If it is the Real-time database that you want to use you’ll probably know and you’ll probably have a specific reason for using that. The fact that it’s real-time doesn’t affect our ability to get real-time data in Firebase, you can build something that has live updates without using the old real-time database.
Although I’m not specifically walking through the functionality for building a live chat application, this is actually the reason I’m using Firebase at the moment is for building a live-chat application with Firestore. Although I’m not walking through it in this tutorial, that’s what you could use this whole setup for.
We’ll click on Create Database to create our Firestore database and then immediately you’re going to get prompted to make a choice regarding Firestore security rules. What we’re actually going to do here is start in test mode. Talking about Firestore security rules you are going to have to choose either lock mode or test mode but we’re going to use test mode. It’s very important to understand that this means that anybody would be able to interact with your database. They could add whatever data they want, read it, delete it, do whatever so you definitely don’t want to use this in a production scenario. It is good for just sort of playing around, having fun, testing things which is why we’re going to use it now. I’ll probably save the actual setting up of five security rules for another video but just know that it is important to set these out before you go live with a real production application.
So, we’ll choose test mode and we will click enable and after just a few seconds our database is set up. So, Firestore users it’s a document-based no SQL database and what that means for us is that we’re not going to actually have to set up anything here. You can manually add some collections and those collections store documents. We’re not going to get into the nitty-gritty of how a document-based or noSQL database works just because that topic is too large to cover right now. One of the main points though is that we don’t need to set up any kind of predefined schema we can just start adding data to it.
Although we can create a collection of messages or users or whatever we want here you don’t actually need to set that up to begin with and that doesn’t mean that you can just store whatever you want. Obviously, you need to have some kind of reasoning or structure behind the data you are actually uploading but it’s just not a requirement to set it up beforehand like it is with say a more traditional, relational database.
With that setup, we’re basically done with the Firebase console. Again, I will point out notice here with the rules has this little exclamation mark to show that they were in dangerous territory here that we have loose rules that are going to allow our database to be interacted with by anyone. Again, just make sure you’re not going live with that stuff.
Now it’s time to jump over into our project/code. We’ve already set up a lot of this stuff in the previous video. This is our Auth Controller that we set up that we were using to authenticate anonymous users and it also handled the initial configuration of our Firebase setup. I’ve actually added a new thing here which you have to add to your Auth Controller as well. You will notice I have this
watchAuthState method here now and so basically this is using the
firebase.auth().onAuthStateChanged to detect when the user either logs in and logs out.
What we’re going to do for our database in a moment is we’re going to listen for when the user has logged in. When that auth state has changed and we’re going to use that to trigger our loading in the data from Firestore. What this method does is it allows us to pass in handler function and that is going to allow us to pass some data back to whatever function we passed in whenever the auth state changes. You’ll see how we use that in just a moment. This is the sort of scenario where I’ll typically use an observable. In this case, we don’t have the RxJS library installed. If you did have that installed you could instead expose some kind of observable here that’s triggered whenever the auth state changes. With that, we set up this detach listener which basically just provides us with a method to tell Firebase to stop listening for the auth state changes. So, we triggered that when we logged out for example. So, again, the basic idea here is we listen for all state changes. We’re actually setting the user whenever that happens and we also passed user information back to the handler function that is passed into this method here.
Now, let’s get into the actual database stuff. To handle this I’ve set up another database controller which is just like our auth service. It’s going to allow us to have a database service in our application and you’ll see I’m importing both of those into the route component and calling the init functions on both to set those up. For this one, when it’s initialized it’ll set up the Firestore database onto this.db and then we’re going to interact with that.
Much like the watch auth state, we’re also setting up a watch messages and this does basically the same thing except rather than watching the authentication state we’re going to watch for new data being added to our messages collection that will eventually exist in our Firestore database. So, again, we set up its detach listener so we can stop listening when we want and then we just call this.db. We want the messages collection and we’re going to order that data by the date it was created. I will limit it to 50 documents and then we have the on snapshot method and then basically every time that data changes when there’s new data added to it, for example, this is going to run here. What we’re doing basically is just building up an array of all the messages that are stored in that Firestore database and then for each of those we just push them into this array here and then we pass that array back to the handler function that was passed in to watch messages. Again, I could use an observable for if you had that installed but this works also.
Then we also have an add message method set up here so basically this will allow us to pass some message string into here. This is going to handle creating a new document for us. You’ll see we’re saying
this.db.collection('messages').add so what that’s actually going to do in our Firestore database here if the messages collection doesn’t already exist it’s going to create that automatically and then it’s going to add that document in the Database section of our project. So, we look at that working in just a little bit but that’s the basic idea.
The document we’re supplying here has a UID which we’re just setting to whatever the users currently logged-in users ID is. A created field that says when it was created by the timestamp and the actual message passed into this method and then any display name that is set for that particular user which if you’re just using an anonymous user and they’re not gonna have a display name unless you specifically set that.
That’s all there is to this database controller here. We just have a way to watch data in the Firestore database so we can get any new data that’s added and pull that into our application and we have a way to add documents to our collection. Again, you have to make sure that these are imported into your root component here and we’ve initialized them and then we can make use of them wherever we want in our application.
For demonstrating this I just have a homepage set up. It’s importing both services. Typically, you would have a separate login page and then have user login go to some other page but we’re going to demonstrate this all on the one page. Some of this is from the previous tutorial. We have this login method being called which is going to use the login anon method to authenticate that user anonymously but we’ve also added some new stuff as well. We’ve set up this state here it’s a member variable called messages and we use state from Stencils so that whenever this gets updated our render function will run so that the template gets updated otherwise the template wouldn’t update when the data changes. This is where we’re going to store those documents that we’re pulling in from Firebase.
What happens here is in our componentDidLoad lifecycle hook we call the watch auth state method that we set up and remember how we could pass a handler function into that so this is that handler function that we’re passing in. When the auth state changes this function is going to trigger and it’s going to have that user information. What we’re saying is if a user is supplied that means that the user has authenticated successfully. We’re to set up this watch messages from the database service which again is the exact same thing. We can pass in this handle a function here that’s going to trigger every time there’s any new messages or any changes. What we’re doing is just setting up those messages onto this.messages so they are stored here with our state. We also reverse those because the general idea behind what I’ve been creating is a chat service. I’m pulling the last 50 messages and showing them in a reverse order.
Then, down in our template, we are just mapping our messages to display each message inside of an
ion-item. Again, that’s not really something that I’m aiming to explain in this video but we’ll try to link to some other content you can check out if you’re not sure how this works with Stencil and JSX.
Then I’ve also just added this button that’s going to trigger adding a test message. I will just trigger this method here and basically that’s going to call our message method from our database service and it’s just going to create a dummy test message here. With all of that set up now let’s jump into the browser and see if all of that works. We can run our application with
npm run start and check out what’s happening in the browser.
Okay, so, just a quick note, I don’t think I did this in the previous video or for the project that has worked on but I did have to come into Stencil Test and just grab my web app that I’ve set up in Firebase and copy this config code which includes an app ID now. I don’t know if that is new or if I just missed that before but in any case, I had to make sure I had that information there and copied into my config otherwise it was complaining about not being able to connect to Firestore. I don’t know if I just miss something or if something actually has changed but yes make sure you do that. Anyway, let’s jump back into the browser now.
We’ll test that login method. Basically, if we click login that should be authenticating us anonymously and then it’s going to start watching our database for messages. As I mentioned, typically, you know this would be on a separate page and then we’d come to this page but for the sake of the test, this is what we’re doing. Click on that and we can see the result of that over here in the console that we have signed in successfully. Let’s see what happens when we click Add Test Message and you can see we immediately get ‘this is a test’ popping up on the screen there.
If we jump back into our console here and go to the Database section again you can see now that we have this messages collection created automatically. We didn’t have to add that through here, it just created it because it didn’t already exist. We can see this document has been added there and you can see the various fields. We don’t have a display name so the author is showing is null. Let’s just add another one and see if that works. Jump back in here again you can see that being at it again. Let’s add three more. You can see each time we add something it is added in the Database section. Just for the sake of testing let’s try add a document through this interface here and see if we can get it showing up right away in our messages. You can see here we have five messages there now let’s just say add document and we’ll just have to copy the structure of our existing document.
We’ll save that and you can see we have our document added there so let’s see if it’s added into here and it is so you see that this immediately popped up on the screen there without us having to refresh or anything like that. We can also see Josh there now because that was the display name which the others don’t have and we have a different avatar because the API I’m using is just giving me a random avatar based on the user ID. You might notice this little error here in the console. This isn’t actually anything to do with what’s going on with Firebase. It is just one of the extensions I have installed, it pops up for me all the time so don’t worry about it.
One final test to do is just to refresh and see that we get our new our existing data popping in and we do so that’s all set up automatically. As soon as we refresh users authenticated it’s going to use that watch message service or method from the database service and it just automatically pulls in that data and then we can add whatever we like.
This was a reasonably simple overview of just hooking up a simple StencilJS and Ionic application to a Firestore database getting some data going both ways, storing some data and pulling some data into our application. As I mentioned there are somethings to be concerned about. Obviously the structure of your data is important. Setting up those Firebase security rules is important so I’ll likely we’ll do another video maybe another couple videos on some Firestore stuff if people are interested in that. If you want, let me know. If you like this video please do feel free to like and subscribe and I will see you in the next video.