This is an example that shows how to create a simple Chat application with the following technologies: AngularJS, Angular Material, Socket IO.
The full example is available on branch master, but you can start from nearly scratch when you checkout branch step_registration.
Demo
Demo is available here: https://angularchatexample.firebaseapp.com
Main features:
Login
Registration
Logout
View/Update Profile
Create room
List rooms
Open room
List users in a room
List messages in a room
Create new message
Source
Git
If you use Git, you can clone the repository of the application with the following command:
Download as zip
If you don’t want / can’t use Git, you can download the source from the following url:
Registration
We have a login form as a starting form, but unfortunately there’s no user we could log in to the chat. For this purpose let’s create the registration form in this section. Extend index.routes.js with the following route:
As you can see from the code above we need a template and a controller too… Create folder registration and place registration.controller.js here with the following content:
Add registration.html with the following HTML:
We need to link somehow the registration form with the login form, so add a registration button to login.html as the following example shows:
Profile
step_profile
Complete the profile.directive.js directive to load the current user:
We also want to save the profile details, so add the following function too:
Extend the template (profile.dialog.html) to load the basic form (between md-dialog-content tags):
In the same template call the function that saves the profile when the user clicks the button:
Let’s upgrade our sidebar to a whole new level. To do this, inject AccountService in the leftnav.directive.js and retrieve the current user:
Let’s create a button on the sidenav to reach user profile (leftnav.html):
We should also display the loggedin user, so paste the following code between the first md-content tags also in the leftnav.html template:
Let’s put the image of the user in the menu. To do this first inject AccountService in the menu.directive.js and query the loggedin user:
Display the user avatar as a button (menu.html), that way the user can click on it and edit its profile:
Create room
There has been no word about rooms yet, so first let’s create the room model as room.model.js file in the room directory:
Don’t forget about the users of a room, so let’s create this model too (room.users.model.js):
Next we have to deal with the room service. Create room.service.js file with the following content:
The room creator button directive is in the create.room.fab.directive.js, but the event handler method is missing. Let’s implement this function:
We need to call this method in the create.room.fab.tmpl.html template:
Add a tooltip too:
And finally compose the create room dialog template too (create.room.dialog.tmpl.html):
List rooms
In this section we will create a panel that lists all available rooms. This panel will be activated from a button in the top menu. Let’s see how to implement all of this!
Add the following features to the RoomService:
Get all rooms:
Get users of a room given with roomId :
Now we create a button in the menu (menu/menu.html) that will open the room list on click:
This is a plain old Angular Material button with a little bit of directive (room-list-opener) on top of it. Wait, we haven’t written this directive yet, so do it now (room/room.list.directive.js):
We need a click event handler in the directive’s link function:
In the event handler let’s use Angular Material’ mdBottomSheet component:
Here we can see the previously defined RoomListController listed as controller but it doesn’t do anything special yet. We want to display all rooms, so we need to query them from the RoomService
The template is missing though, so add a room.list.tmpl.html file with the following content:
Open room
In this section we will create a tab layout for the opened rooms.
First things first, add a getRoom function to the room.service.js file:
We also need a service that can keep tracks of opened rooms (opened.room.factory.js):
Add the following functions to the opened.rooms.factory.js:
Index of currently selected room:
Get room by index:
Get all opened room:
Add room to opened rooms:
Remove room from the opened rooms:
Is there any opened room?
Is the room opened?
Synchronize previously opened rooms from local storage when the factory is created:
When you click a room in the list, it would be awesome to actually open the selected room. That means a new navigation aka state in the index.route.js file:
As you can see we also need a RoomItemController for this state, so create room.item.controller.js file in the room directory with the following content:
Don’t forget to subscribe on your favourite socket.io events in the controller:
Next create the basic room view in room.item.html file:
Declare the openedRoomsFactory dependency in room.list.directive.js file, and implement the function responsible for opening a room:
Add an event handler to room.list.tmpl.html:
For our tab layout we need to create the RoomsController too (room.tabs.controller.js):
room.tabs.controller.js:
In the controller we need to synchronize the opened rooms:
When you close a tab, you have to remove the room from the factory:
The current index and navigation state has to be updated too when you click on a new tab:
Next create the view for the tab layout (room.tabs.tmpl.html) with the following code:
Don’t forget about unsubscribing the user when leaving the room! To achieve this, add the following changes to the logout method of the account.service.js file (add socketFactory and openedRoomsFactory dependencies too):
Remove opened rooms too:
Routing needs to be extended in the index.routes.js file. There is a state called “rooms” already, add to this the following changes:
Add openedRoomsFactory dependency to create.room.fab.directive.js and following changes too (here you make sure when opening a new room it will be listed in the opened rooms and actually opened too):
Messages
First create a directory called “message” for the message aspect. Then add a message.model.js file in this directory with the following content:
Next create the service that is responsible for message handling (message.service.js):
Add the following functions to the service:
Get Messages in a room:
Create message in a room:
To make these two functions available from the outside add the following statements:
Add a function that handles message creation in room.item.controller.js:
Add the missing socket handling:
Open room/room.item.html template! Here create an Angular Material list, that will display the roomItemCtrl.messages variable:
Create new message:
Previously we used message directive, but it doesn’t really exist. So create message.directive.js in the message folder:
As last step create the template for that directive with the following content:
Now you are ready, and hopefully you can use your brand new chat application.
If you stuck at some step, you can checkout the proper branch to this step from the Git repository.