This might be the most dreaded question among new developers on how to make an app with Angular and Socket.io. As most of the apps make use of sockets for real time communication of the Frontend with the Backend. So, today i will be talking about how to integrate socket.io with an Angular app. This code would work for all Angular versions above Angular 1.

Updated — This article has been updated in December 2020 to handle the latest version v3 changes of socket.io

Creating a NodeJS Express app

Let’s start by creating a node project first.

Create a new directory and then enter it.

mkdir socketio-node

This will create a empty folder with name socketio-node.

We’re going to use the Node.JS web framework express. Make sure Node.JS is installed on your system.

First let’s create a package.json manifest file that describes our project.
Create a file named package.json and paste the below code into it.(You can also do it with npm init)

{  
	"name": "socketio-node",
  	"version": "0.0.1",
	"description": "my first socket.io app",
  	"dependencies": {}
}

Now, in order to easily populate the dependencies property we need to install express, type this in the terminal.

npm install express

It will install and add the latest version of express into our project and your dependencies will now look like

"dependencies": {
  "express": "^4.17.1"
}

Now that express is installed we can create an index.js file that will setup our application.

const app = require('express')();
const http = require('http').createServer(app);

app.get('/', (req, res) => {
  res.send('<h1>Hey Socket.io</h1>');
});

http.listen(3000, () => {
  console.log('listeninghttp on *:3000');
});

This code is explained in the following steps:

  • Express initializes app to be a function handler that you can supply to an HTTP server (as seen in line 2).
  • We define a route handler / that gets called when we hit our website home.
  • We make the http server listen on port 3000.

If you run node index.js you should see the following:

Opening http://localhost:3000 in browser would look like:

Integrating Socket.io with NodeJS

Now let’s integrate socket.io into our node app. Firstly, we need to install socket.io dependency into our app. Run this in the terminal.

npm install socket.io

This will install the module and add the dependency to package.json. Now let’s edit index.js to add it:

const app = require('express')();
const http = require('http').createServer(app);
const io = require('socket.io')(http, {
  cors: {
    origins: ['http://localhost:4200']
  }
});

app.get('/', (req, res) => {
  res.send('<h1>Hey Socket.io</h1>');
});

io.on('connection', (socket) => {
  console.log('a user connected');
  socket.on('disconnect', () => {
    console.log('user disconnected');
  });
});

http.listen(3000, () => {
  console.log('listening on *:3000');
});

Notice that I initialize a new instance of socket.io on line 3 by passing the http (the HTTP server) object and the cors options(updated for socket.io v3) to allow our angular localhost url, you can put in the url or your frontend client, in my case it was localhost:4200
Then I listen on the connection and disconnection events for incoming sockets, and I log it to the console.

Our Backend is good to go for now, we will come back to our node code when we will implement more events further on.

Creating an Angular app

Let’s start by creating an Angular app now. I will be creating a new Angular app from scratch, while most of you would already have one created with you.
Those who already have a working Angular app can skip the following code:

npm install -g @angular/cli
ng new socketio-angular

This would install the latest version of Angular CLI and create a new Angular app from scratch.

Now let’s add socket.io dependency in our Angular app.

cd socketio-angular
npm install socket.io-client

This would install the latest socket.io-client library in our Angular app.

Creating a socket client service

Now let’s start by creating a service to handle socket.io connection. I would create a root level singleton service named socketio.service.ts and include that in AppModule . You can create the service according to your project structure.
You can create the service by running the following command.

ng g s socketio

This would create a service named socketio.service.ts . The directory structure would look something like this. This is just a simple one page demo, so i added the service into the base folder like this.

Now, go into the socketio.service.ts file and import the following:

import { io } from 'socket.io-client';

Now let’s add the socket endpoint that we would connect the socket to inside environment.ts file.

export const environment = {  
	production: false,  
	SOCKET_ENDPOINT: 'http://localhost:3000'
};

Now let’s try to connect to our socket and create a socket conenction. First we need to add SocketioService into our AppModule and inject the service into our app.component.ts . Let’s add the service into our providers first. In app.module.ts do this:

@NgModule({
    declarations: [AppComponent],

    imports: [BrowserModule],

    providers: [SocketioService],

    bootstrap: [AppComponent]
})

export class AppModule { }

And let’s go to socketio.service.ts and write a socket init function.

export class SocketioService {

  socket;

  constructor() {   }

  setupSocketConnection() {
    this.socket = io(environment.SOCKET_ENDPOINT);
  }
}

This will declare a variable named socket and then after calling the setupSocketConnection method, socket variable would be containing the connected socket object.

Now, let’s call this method from app.component.ts inside ngOnInit.

export class AppComponent implements OnInit {
  
  title = 'socketio-angular';
  
  constructor(private socketService: SocketioService) {}
  
  ngOnInit() {
    this.socketService.setupSocketConnection();
  }
}

If your are using Angular 6 and above, you might run into this error.

Uncaught ReferenceError: global is not defined

This is because on version 6 of Angular CLI Angular team removind the shim for global and other node built-ins. If we are using a library that assumes these globals are present(socket.io-client in our case), you can try manually shimming it inside your polyfills.ts file:

// Add global to window, assigning the value of window itself.

(window as any).global = window;

Adding this line to your polyfills.ts file would fix the issue and your app would be working again. To read more about the above issue, follow this link.

After running the Angular app now, you can see the socket connected and our node app console showing a user connected like this:

Disconnection

Now, let's try to disconnect the socket, we will use the ngOnDestroy hook of Angular.

ngOnInit() {
  this.socketService.setupSocketConnection();
}
  
ngOnDestroy() {
  this.socketService.disconnect();
}

In your socketio.service.js file add this method for disconnection

disconnect() {
    if (this.socket) {
        this.socket.disconnect();
    }
}

When you disconnect the socket or close the webpage, you can see user disconnected message on console.

With this, we have completed our initialization of sockets. Now we will learn about how to emit and listen to events.

Event Handling

Let’s register an event called my message inside our index.js in nodeJS project file and console the data and we will emit the same event from Angular app.

io.on('connection', (socket) => {
  
  console.log('a user connected');
  
  socket.on('disconnect', () => {
    console.log('user disconnected');
  });
  
  socket.on('my message', (msg) => {
    console.log('message: ' + msg);
  });
});

And let’s emit the same event from Angular code

setupSocketConnection() {  

  this.socket = io(environment.SOCKET_ENDPOINT);  
  
  this.socket.emit('my message', 'Hello there from Angular.');
  
}

This code would emit the event named my message and it would print the following on our node console. You can see the message ‘Hello there from Angular’. Our custom events are now working.

Broadcasting Event

Now, let’s emit an event from the server side. We will broadcast the event to all connected users. We will broadcast the same message that we received from client and prepend a server string to it.

io.on('connection', (socket) => {
  socket.on('my message', (msg) => {
    io.emit('my broadcast', `server: ${msg}`);
  });
});

Let’s add an listener for my broadcast event on our Angular app now.

this.socket.on('my broadcast', (data: string) => {
  console.log(data);
});

After doing this, you can check your browser console, it would print something like this. It prints a message from server, that emitted the broadcast.

We have covered the basic parts of connecting an node socket.io app with an Angular app.

BONUS: Authentication

You can also send query parameters to the Backend when connecting to the socket by using options with url in a connection.

this.socket = io(environment.SOCKET_ENDPOINT, {
  auth: {
    token: 'cde'
  }
});

To fetch this information on the Backend, we have to do it like this:

io.on('connection', (socket) => {
  let token = socket.handshake.auth.token;
});

This would return the value cde passed by Frontend.

You can check all of the above written example code at my github.

This concludes my article about creating a real time application with Angular and Socket.io with NodeJS. I have covered the basics of connecting the apps. There is a lot more information on sockets that can be explored like rooms, online offline status, sending more data, fetching online users. This information cannot be covered in an single article. Will write on these topics if you liked my work on this blog.

Do write down your reviews and remember to subscribe below for more content like this.

Liked my work? Buy me a coffee.