This tutorial is part 3 of a 5 part series. If you would like to see part 2 you can go to it here.
Part 1: Installing necessary components. Generating a blank app through Angular CLI. Add Bootstrap for styling. Create Firebase account. Install and setup Firebase through NPM.
The code for part 1 can be found here.
Part 2: Add user login through their Google account. Create the Login Page and Home Page Components. Add asynchronous monitoring of the logged in status. Redirect to the Home Page when logged in and to the Login Page when the user logs out.
The code for part 2 can be found here.
Part 3: We will add a simple chat app that stores messages into a Firebase Realtime Database.
The code for part 3 can be found here.
Part 4: We add Email/Password user authentication using Firebase.
The code for part 4 can be found here.
Part 5: COMING SOON Adding the ability for a user to edit or delete any messages that they have sent.
Firebase offers a lot to speed up the development of an app, while allowing for growth. I come from a background of Symfony and SQL Databases, which are great but take a lot of time. The day that I experienced what Firebase and Angular 2 had to offer I have not looked back since. I even removed Sequel Pro from my computer!
There are multiple things that make Firebase’s Realtime Database a technology worth learning.
- It remains responsive regardless of internet connectivity. In a Symfony app an Error like that is usually game over.
- For example: while using the chat app we are building if you turn your wifi off and send messages to it. Your messages show up on screen as if they were sent, but really they are queued up and will be sent when you have internet again. When the internet comes back on not only are your messages sent, but any other messages that happened during that time show up, all without the page reloading!
- It handles the complexity of realtime synchronization for you
- It also is in the cloud and ran by Google, so your database will always be up and available.
- It is a NoSQL database. So adding stuff to the database is amazingly easy! You don’t have to update the schema and make sure your types are correct (not to mention updating the queries that don’t work bc of that update to the db) you just change it and it works!
There are multiple different ways to develop an app, for me I like to build the services and the functions I will need. Then I build the components to use them.
We need to add a few things to the
AF service provider. Update
src/providers/af.ts to look like this:
There are a few things worth noting in this chunk of code. In the constructor we added
this.messages = this.af.database.list('messages'); this creates an AngularFire2 reference to our Firebase Database so we can read/write from it. We also added places to hold the
We also add a function to save new messages to the db, by pushing our message object onto the Firebase Database reference. When we use push to add a message to the Database, it will automatically generate a unique key. The picture below shows what a message looks like when it gets saved to the database:
Note: There are other methods we could use to add data to the database. There are set, update and remove that are also available. Set replaces the current value in the db with the new one. Update is less destructive and will update the data. Remove will delete the object from the database.
When we save a message to the database we are storing the
timestamp. We need to make sure that the the
The best way to do this would be to set them in our authentication subscriber. This is located in the constructor in
src/app/app.component.ts. It subscribes to any change in the authenticated user. When the user logs out, this subscription sends us to the login screen. Update the constructor to look like this:
When the user is logged in we set the
Before we add the HTML we are going to use, lets add some stuff to
home-page.component.ts. We need to add access to the Service Provider. Update the code to look like this:
AngularFire2 synchronizes data as lists using the
FirebaseListObservable object. We point that to the
messages reference we made in our service provider. We also add a variable called
newMessage. We will use a two way binding to the input field so it will have the value of the new message that has been typed.
Note: Since we are retrieving all the messages we need to use FirebaseListObservable, but we also have the option of FirebaseObjectObservable. We would use that if we were retrieving a single message.
In order for that two way binding to work we need to add
FormsModule to the imports section of
app.module.ts or we will get a gnarly error later:
Lets first add the CSS that will style our Message system to
Now we will add the HTML to
home-page.component.html. A lot is going on in this code. I will attempt to break it down bit by bit by labeling the key points.
Point 1: This is where we bind a loop to our messages. Remember that the messages object is a
FirebaseListObservable. This means it will asynchronously stay current with the db. Any changes to the messages in the database will immediately be reflected here. We have to have to specify this relationship in the loop by adding
Point 2: In the CSS I have classes called
me. Which puts the correct css for the chat bubble depending on if it was the active users or not. Using the syntax
[class.you]="isYou(message.email)" binds the presence of the class
you to the truthfulness of the function
isYou. To make both
isMe work we need to add those functions to
home-page.component.ts. They return true or false if the email on the message posted matches the email of the current user.
Point 3: We two way bind the input to the textarea to the variable
newMessage by doing this
[(ngModel)]="newMessage". We also want the user to be able to submit their message by hitting enter, so we add the event
keyup.enter to trigger our
sendMessage function. We also bind the
click event on the SEND button to trigger the
sendMessage function also.
Now when a user sends a message they get stored in the Firebase Realtime Database!
ng serve from the terminal to very your app is working and the data is being persisted to the database.
Now that we have a working messaging system there is only one thing left that does not work the way that I would like it. When our app loads up the oldest message appears first. I would rather it scroll to the bottom to show the most recent messages.
To do this we need to add import
ViewChild from the core Angular 2 library. We will also need to make a function that will achieve this. Add this code to
We need to add the
ngAfterViewChecked function bc it gets called after every check of the component’s view, which will trigger the
We bind an
ElementRef variable to
myScrollContainer to the local variable
scrollMe. We need to add that variable to
home-page.component.html so that our app knows which div needs to be scrolled.
Now our messaging system functions how it should!
At this point we have a working messaging app that uses Firebase to Authenticate users and store the chat messages in the Realtime Database. I hope this helps you learn how to harness the power that Angular 2 and Firebase have.
If you have any questions please don’t hesitate to ask me! :)
Oh yeah I almost forgot. I do realize the title says it is a CRUD and we are not updating or deleting anything form our Database. I will be adding a 5th part to this series so that users can edit their own messages or delete them.