Posts on this Category



Tutorial: Creating a Realtime Notification System in Angular and Nodejs

Notification System Demo
Notification System Demo

In this post I’m going to show you how to create a simple realtime notification system using Angular, Nodejs and Socket.io. It will offer a page where we will be able to create notifications and broadcast it to all the online users. I’ll be making it as basic as possible, once we’re done we can add more functionalities. This application will have the frontend and the backend separeted in 2 different projects, we’re going to use Angular in the frontend and Nodejs in the backend. Let’s start with the backend.

Creating the Nodejs Project

I’m using Expressjs to create the Node.js project, if you don’t have express you can install it globally via:

npm install express-generator -g

After installing it you can create your project with the command:

express notifications-backend

In this case ‘notifications-backend’ is the project name, but you can give a name of your choice. Now you already have a basic expressjs project, if you run your project with npm start and type the url localhost:3000 on your browser you’ll see a welcome page. By default expressjs create some views for us, we’re not going to be using them though, so feel free to delete them if you want. All of our views will be on the frontend project, this one will only be responsible for managing the notifications.

Creating the Socket.io Server

The next step is to add socket.io to the project:

npm install --save socket.io

Socket.io is what makes our application realtime, it’s event-based, which means when an event happens, it triggers something. All the events are specified by us, we can create as many as we want, but our application only needs two, I’m going to name them create notification and new notification.

create notification: This event will be emitted by the client-side when a user creates a notification. The server will always be listening to this event, this is how it will know a notification was created.

new notification: This one will be emitted by the server-side when it receives a newly created notification. As opposed to the previous event, this one will be listened by every client, once they receive this event they will just show the notification to the user.

This is our server-side socket.io code, I’m putting it on the app.js just bellow the var app = express(); line.

var http = require('http');
var server = http.createServer(app);
var io = require('socket.io').listen(server);
io.set("origins", "*:*");
server.listen(8000);                                 
 
io.on('connection', function(socket){                
  socket.on('create notification', function(data){   
    socket.broadcast.emit('new notification',data);  
  });
});

Before we analyze the code we should know the socket.io on function, that’s the function we use to add event listeners to the application, it receives the event name and a callback function that will be executed when the event fires. You should also be familiar with the function emit and broadcast.emit, the first one emits an event to all the clients as the second emits to everyone except the client who fired it.

Now If you take a look at the code you’ll see that the first 5 lines are just to create the socket server, next I’m adding an event listener to the connection event, so every time a new client connects this event will call a callback function that adds a listener to the create notification event, which when triggered will emit the new notification event broadcasting the message to all the users.

We are pretty much done with the backend now, time to start working on the frontend!

Creating the Angular Project

If it’s the first time you’re using Angular you have to install @angular/cli before you proceed.

npm install -g @angular/cli

Now you can create your project.

ng new notifications-frontend

Again, notifications-frontend is my project name, you can change it if you want. The command above will download and install all the dependencies on your project, so it may take a while. After creating the project we have to install socket.io on this one as well, but the installation is a little bit different from the backend, click here to see the instructions.

Now we have the basic project structure, we’ll be creating two components, app.adminComponent.ts and app.userComponent.ts, the first one is the page where the admin will be able to send notifications to all the other users, and the second is a component that represents any page that a user have access to, its only functionality will be to receive the notification.

app.adminComponent.ts

import { Component } from '@angular/core';
import { Socket } from 'ng-socket-io';
 
@Component({
  selector: 'admin-component',
  templateUrl: './app.adminComponent.html'
})
export class AdminComponent {
 
   constructor(private socket: Socket) {}
 
   sendNotification(){
      this.socket.emit('create notification','Notification Test');
   }
}

Here we have the admin-component, note that I’m declaring the socket on the constructor, besides that I’ve created only one function, the sendNotification, which will be responsible for emitting create notification event. Remember when we created its listener on the server side? This is how it’s going to be triggered.

You have probably noticed that this component uses a template. Here is the code:

<div style="text-align:center">
   <button (click)="sendNotification()">Send Notification</button>
</div>

Nothing special here, it contains only a button that calls the sendNotification function.

app.userComponent.ts

import { Component } from '@angular/core';
import { Socket } from 'ng-socket-io';
 
@Component({
  selector: 'user-component',
  template: ''
})
export class UserComponent {
 
   constructor(private socket: Socket) { 
      socket.on('new notification', function(data){
         alert(data)
      });
   }
}

This one is even simpler than the previous, the only thing I’m doing here is adding an event listener to the new notification event, which is the event for receiving a notification. Once it fires it will show the notification message to the user with an alert dialog.

Routing and Navigation

We’re almost done, the last thing we have to do is to add the routes, that’s what will allow us to navigate between the two components. We will define two routes, user and admin, so our components will be accessed by the urls http://localhost:4200/user and http://localhost:4200/admin respectively.

Here is how we can define the routes on the app.module.ts file:

//other imports
import { RouterModule, Routes } from '@angular/router';
 
const appRoutes: Routes = [
  { path: 'user', component: UserComponent },
  { path: 'admin', component: AdminComponent },
];
 
@NgModule({
  imports: [
    RouterModule.forRoot(appRoutes),
    //other imports
  ],
  ...
})
export class AppModule { }

As you can see I’ve created the array appRoutes, here is where we declare all of our routes mapping the paths to the components, then we pass it to the RouterModule.forRoot function on the module imports.

Lastly let’s open the app.component.ts, that’s the default component that was already there when we created the project. We’re only using this component to put the router-outlet, which will just display the component that matches the path on the Url.

import { Component } from '@angular/core';
 
@Component({
  selector: 'app-root',
  template: `
    <router-outlet></router-outlet>
  `
})
export class AppComponent { }

That’s it guys! Your application should be working now, hope you liked the tutorial. If you have any doubts please let me know in the comments.

How to add Socket.io to an Angular application

Lots of people get confused when trying to use Socket.io with Angular, some developers just add the script to the HTML and start using it, even though it works I don’t recommend doing this way, let me show you the right way to use it with Angular.

After creating your angular project install ng-socket-io via:

npm install ng-socket-io --save

This is an Angular specific Socket.io module. After the installation is complete you have to configure socket.io in your app.module.ts, you basically just have to add the imports and inform the server url:

...
import { SocketIoModule, SocketIoConfig } from 'ng-socket-io';
 
const config: SocketIoConfig = { url: 'http://localhost:8000', options: {} };   <-----------------
 
@NgModule({
  declarations: [
    AppComponent
  ],
  imports: [
    BrowserModule,
    SocketIoModule.forRoot(config)     <-----------------
  ],
  providers: [],
  bootstrap: [AppComponent]
})
export class AppModule { }

Next, open the tsconfig.json and add the “include” attribute at the end, this will prevent some errors when building your project. Make sure the file looks like this:

{
  "compileOnSave": false,
  "compilerOptions": {
    "outDir": "./dist/out-tsc",
    "sourceMap": true,
    "declaration": false,
    "moduleResolution": "node",
    "emitDecoratorMetadata": true,
    "experimentalDecorators": true,
    "target": "es5",
    "typeRoots": [
      "node_modules/@types"
    ],
    "lib": [
      "es2017",
      "dom"
    ]
  },
  "include": [
    "src/**/*",
    "node_modules/ng-socket-io/index.ts"
  ]
}

That’s it! Now you just have to import it to your component and start using it:

//importing 
import { Socket } from 'ng-socket-io';
 
//usage example
constructor(private socket: Socket) { 
   socket.emit('test','test');
}	
}

@angular/cli error when creating project: Unexpected token =

After installing @angular/cli lots of people get this error when trying to create the fist angular project:

SyntaxError: Unexpected token =
   at exports.runInThisContext (vm.js:53:16)
   at Module._compile (module.js:373:25)
   at Object.Module._extensions..js (module.js:416:10)
   at Module.load (module.js:343:32)
   at Function.Module._load (module.js:300:12)
   at Module.require (module.js:353:17)
   at require (internal/module.js:12:17)
   at Object.<anonymous> (C:\Users\a\AppData\Roaming\npm\node_modules\@angular\cli\models\config.js:3:18)
   at Module._compile (module.js:409:26)
   at Object.Module._extensions..js (module.js:416:10)

The solution is very simple, just download and install the newest version of nodejs, this should fix the problem.