Case Study: Creating a chat room with Angular

Introduction

The goal of this project was to create an application that sends and receives messages in real time. This was written using the Angular framework, made pretty with UI Bootstrap and uses a Firebase database for storage.

Why Angular?

Angular is a JavaScript framework for building primarily CRUD (create, read, update, delete) applications. Angular is ideal for single-page applications (SPAs) which means the page doesn't have to refresh every time you click on something (think Gmail). 

It can be easy to confuse a framework with a library so let's quickly look at the differences.

A library, like jQuery, is a collection of pre-written code that you link to. This code simplifies common tasks and functions. 

A framework, such as Angular, provides the structure of an application. The framework determines how the application works in general and the code we write fills in the details.

Milestones

1) The Setup

The first step was setting up the development environment. This included installing NodeJS to locally serve up the application. Bloc helps make the configuration process a bit easier by providing a starter project repository. After pulling this down and renaming it, it was pushed back up to GitHub. 

From here I added Angular, UI-Router and AngularFire to the project by including it in the body of index.html. After this a controller and template were made so I could then test the application using npm start then viewing it on the local host. 

That completed the initial configuration, allowing me to push it up to GitHub and start building out the application. 

2) As a user, I want to see a list of available chat rooms

The goal here was to make it so a user can see a list of available chat rooms. I started off by creating a handful of "fake" rooms in firebase so there was something to query and display on the site. 

After this, I created a Room factory in Angular that defines all Room-related API queries. Next, I had to create a controller to display the queried rooms in the view. The controller was injected with the Room service then I displayed the rooms in the template using ng-repeat. 

3) As a user, I want to create chat rooms    

In this checkpoint, I started off by creating room objects with AngularFire. From here UI Bootstrap's service was injected to allow for the easy creation of a simple modal form to submit new room's data using ngSubmit. 

The Bootstrap library was included in the index.html, the proper dependencies were injected and the methods were added. At this point, I was able to view the array of rooms update in real time. 

4) As a user, I want to see a list of messages in each chat room

The first step in this checkpoint was creating a container to display an individual room's content. This was done by styling a container for holding a list of messages to the right of the list of available chat rooms. The active room is stored in a $scope object in the main controller to allow the title of the active room to change every time you visit a click one.  

Next I had to associate messages with a room. This was done by using a reference to the parent data (the room) in the child data from Firebase. I created a few messages manually to test querying messages. 

From here I created a message factory in angular that defined all messaged related API queries. I used the child() method on the $firebaseArray service to query messages. Since messages depend on the ID of a room I had to pass in an argument into the getByRoomId method that contains the roomId associated with a rooms message. 

5) As a user, I want to set my username to display in chat rooms

The challenge now was to efficiently store a username. A common way to store a string in a browser is using cookies. Angular has an external module to do this (ngCookies). 

The next step was requiring each user to enter a username when they visit Bloc Chat for the first time. I created an angular module using the .run() block to make sure that the username is set when the app is initialized. This was done by injecting the $cookies service into the run block's dependencies to check for the presence of a cookie holding the username. 

If there isn't a username present I made it so another UI Bootstrap modal pops up requiring a user to enter one. No cancel option was provided so the user has to create one to proceed. 

6) As a user, I want to send messages associated with my username in a chat room

Sending messages is fun but it would be useless if we didn't know who the messages were coming from. To make this happen I added a method to my Message factory called send that took a message object as an argument and submitted it to the Firebase server. 

To make sure the messages that a user sends are associated with their username I used the username property and populated it by injecting the $cookies service and referencing the current user object on it. 

Conclusion

This was a great introduction to Angular. I feel like I have a good high-level understanding of the various components that make it work but not enough knowledge to build out an app from scratch. I'm excited to move onto studying the Ruby on Rails framework where I'll be diving much deeper into the details.