Chat Application with Angular and Socket.IO

Introduction

We will use RxJS, Angular, express (Node.js) & Socket.IO to make a chat application. We will get to see how useful RxJS can be in this scenario. For the purpose of making things smooth and easy we will be using Angular CLI to generate basic client structure and get us a boilerplate for simplest working Angular application. On the back-end we will use Node.js with express and Socket.IO. Reasoning behind this is that Socket.IO is very easy to set up and work with. Furthermore, it provides both server and client side libraries. Socket.IO primarily uses WebSocket protocol to enable real-time bidirectional communication.

If you wanna jump directly to part where we use RxJS to handle the chat messages click here.

Lets get started!

 

Socket.IO server setup

If you do not have Angular CLI installed you can install it quite easily:

npm i -g @angular/cli

 

Set up folder structure

To keep things clean we are gonna create new rxjs-chat folder for our little project. It should serve as root folder for Angular and Socket.IO apps.

Lets create a basic Angular app using Angular CLI. In our project folder launch your favorite terminal and run the following command:

ng new rxjs-chat

Give it a bit of time. After its done creating basic structure and installing npm packages we will rename newly created Angular project folder to client. After that, in the same root folder create folder server for our Socket.IO server. Now we have two folders inside our rxjs-chat folder:

  • client – Angular client app
  • server – soon to be Node’s Socket.IO server

 

Installing local packages

In the server folder we will generate package.json file by running the following command:

npm init -y

After that we will install our dependencies and save them to package.json:

npm install express socket.io --save

In the same folder we will create index.js file for our server app. Content of the file should be as following:

We create an instance of express and store it into app variable. After that we create server with http module. Then we pass express to http.Server() method. Express will serve as the handler for requests to our server. In return we get the instance of server which we store in server variable.

In the next two lines of code we bind the socket.IO with our http server:

let socketIO = require('socket.io');

let io = socketIO(server);

After that we listen for connection event of socket.IO and we log once a user has established a connection with the server. Finally we start the server and listen on given port, in our case it is port 3000.
Lets actually start our server by running the following in server folder:
 
node index.js
 
Consequently you should get the following message: “started on port: 3000”.
 
 
 

Connecting to Socket.IO

We have a server running on port 3000. Now it is time to see how we can connect to the server from our Angular app. For this we will need to install Socket.IO client library. We will run the following command in our client folder:

npm install socket.io-client --save

While we are at it lets run the Angular app via Angular CLI:

ng serve -o

Now we got our app running. We can see that our default browser just opened a new tab pointing at localhost. That is why we used -o argument to open the browser.

 

Creating service for communication with server

I am gonna name it chat.service.ts app.chat.service.ts and place it inside of src folder. Service is gonna be as simple as possible for now:

 
Adding the service to module providers

Also, lets add our ChatService to providers list inside of AppModule in app.module.ts file:

 

Injecting the service in our component

Finally, we are going to import and use the service inside of our app.component.ts file:

import { ChatService } from './app.chat.service';

And we will inject the ChatService in our constructor:

constructor(chatService: ChatService) { }

As a result we have the following file:

If everything went as expected after saving the changes you should see the ‘user connected’ message in the terminal where you started node app:

$ node index.js
started on port: 3000
user connected

 

Hence, we can say we finally managed to connect to our Socket IO server. Now it is time to actually send some data via Socket IO events.

 

Sending a message to Socket.IO

Time to enhance our so far simple ChatService with an option to send a message to server:

For this to work we have to use sendMessage() from our AppComponent:

Finally, lets provide user with a simple text input and a button so he can send a message:

For this all to work we have to listen on the server for ‘new-message’ event that we emitted from ChatService:

socket.on('new-message', (message) => {
console.log(message);
});

Now our index.js looks like this:

If you want to play around with the code you can find it at my GitHub repo – rxjs-chat.

 

 

Communicating with other users

For our message to get broadcasted to other users all we have to do is change the console.log(message) inside of our ‘new-message’ event callback to io.emit(message):

And what does io.emit() do? In simple words it sends an event to everyone connected to the server.

Lets communicate with our server via ChatService. We will add a new method to our service for this purpose – getMessages. It will return an Observable that we will create with Observable.create() method. Every time socket receives a new messages we will use observer.next() to forward it to observers.

After that we subscribe to this Observable from our AppComponent:

We created a new messages array where we will store messages received from server. We will have to show those messages in our template. That is perfect use case for ngFor:

 

Summary

Now we have a simple chat application working. Users do not have usernames and we do not have chat-rooms, but we will talk about that in one of future posts.

In the next post we will see how we can handle chat messages with RxJS.

Ibrahim Šuta

Software Engineer, Mentor and Consultant interested and specialising in ASP.NET Core, C#, JavaScript, Angular, React.js. Experienced in MeteorJS, Node.js, ASP.NET, Windows Forms and Web Forms as well.