Push Notifications using Angular

  •        0
  

We aggregate and tag open source projects. We have collections of more than one million projects. Check out the projects section.



Notifications is a message pushed to user's device passively. Browser supports notifications and push API that allows to send message asynchronously to the user. Messages are sent with the help of service workers, it runs as background tasks to receive and relay the messages to the desktop if the application is not opened. It uses web push protocol to register the server and send message to the application. Once user opt-in for the updates, it is effective way of re-engaging users with customized content. To know more on the notifications, refer the article introduction to push notifications.

Angular provides a wrapper module for service worker(@angular/service-worker) which will make easy for developers to quickly implement the push notifications to their application.

Push notification on the contrary it destructs the user if he doesn't like it. Browser takes the responsibility of sending the messages only if user accepts the messages and it also maintains its own push service through which push messages can flow to the browser. So application has to send the message to push service and it sends the messages to user if he allows it.

In this article, I will explain how a simple web application subscribes to notifications and receives the notifications. Notifications are created by backend service, which sends messages to the web application. We will also see how we can send recurring notifications or customized message from the backend service.

Two applications will be created, one client application which will receive the message and another notifications backend to send the message to client application. All the communications like creating the subscriptions, sending the messages, pushing the messages happens through web push protocol.

Angular push notification block diagram

We need to create unique Voluntary Application Server Identification (VAPID) keys using which web push protocol communication happens between the push service and client application or push service and notifications backend. To install and generate the web push VAPID keys, please use below command

  yarn global add web-push

web-push generate-vapid-keys --json

It generates vapid keys with public and private key combinations. Public key will be used by the client and public and private key combinations will be stored in notifications backend service.

{
    "publicKey":"BCpUjGH5GSvUeMqI33Xh5xe6BA-awWgTS6B82j6V6GYUsVATgT41qeAJ67fZ1F5srSzt6VXu3cG6slBKpgX_IAA",
    "privateKey":"vOJawCw2OOTUjXjeFiIp5GHPcNXlVzWCXIHd2twPBbs"
}


Apart from that, angular cli, angular pwa, http-server need to be installed. To know more about Angular, refer installing and getting started with Angular and Service worker guide

Create Client Application

Create an angular push notifications project using the below command.

    ng new angular-push-notifications

Then in the app component inject the service worker and check if service worker is enabled. If it is enabled, request for subscription with VAPID server public key to the push service with the help of service worker. If we get the subscription successfully, it need to be passed to notifications backend service through notification service. This subscription details is required for the backend to send the messages.

File: app.component.ts

 import { Component } from '@angular/core';
 import { SwPush } from '@angular/service-worker';
 import { PushNotificationService } from './push-notification.service';

 const VAPID_PUBLIC =
    'BCpUjGH5GSvUeMqI33Xh5xe6BA-awWgTS6B82j6V6GYUsVATgT41qeAJ67fZ1F5srSzt6VXu3cG6slBKpgX_IAA';

 @Component({
     selector: 'app-root',
     templateUrl: './app.component.html',
     styleUrls: ['./app.component.css']
 })

  export class AppComponent {
     title = 'Angular Push Notifications Demo';

  constructor(swpush: SwPush, pushNotificationService: PushNotificationService) {
     if (swpush.isEnabled) {
        swpush.requestSubscription({
           serverPublicKey: VAPID_PUBLIC
       })
    .then((subscription) => {
       console.log(subscription);
       pushNotificationService.sendSubscriptionToTheServer(subscription).subscribe((data)=>console.log(data));
    })
     .catch(console.error);
   }
 }
}

File: push-notification.service.ts

 import { Injectable } from '@angular/core';
 import { HttpClient } from '@angular/common/http';

 const SERVER_URL = 'http://localhost:3000/subscription';

 @Injectable({
    providedIn: 'root'
 })
 export class PushNotificationService {

 constructor(private http: HttpClient) { }

 public sendSubscriptionToTheServer(subscription: PushSubscription) {
       console.log('send subscription');
       return this.http.post(SERVER_URL, subscription);
   }
}


Service worker works in prod environment only in angular application. So we need to build the application with "ng build --prod". Then application can be opened up as below

    http-server -c-1 dist/angular-push-notifications

 

When we open the application, service worker in browser requests for notifications once enabled, it allows to send the message.

 

Notifications Backend Service

Create the node js backend application using the command.

   npm init

Then add the node modules like CORS to enable cross site origin request, body parser to encode and decode the JSON text, web-push for the web push protocol communication and express framework for writing the backend service.

  yarn add body-parser cors express web-push

 

Now web push VAPID details are registered with private and public key. Then subscribe notifications post rest API service is created which will receive the subscription details from the angular application and store it in the temp object.

File: server.js

 const express = require('express');
 const webpush = require('web-push');
 const cors = require('cors');
 const bodyParser = require('body-parser');

 const PUBLIC_VAPID =
         'BCpUjGH5GSvUeMqI33Xh5xe6BA-awWgTS6B82j6V6GYUsVATgT41qeAJ67fZ1F5srSzt6VXu3cG6slBKpgX_IAA';
 const PRIVATE_VAPID =
         'vOJawCw2OOTUjXjeFiIp5GHPcNXlVzWCXIHd2twPBbs';

 const app = express();
 app.use(bodyParser.urlencoded({ extended: false })); 
 app.use(bodyParser.json());

 const fakeDatabase = [];

 app.use(cors());

 webpush.setVapidDetails("mailto:nagappan08@gmail.com", PUBLIC_VAPID, PRIVATE_VAPID);

 app.listen(3000, () => { console.log("server started on port 3000"); });

 app.get('/', (req, res) => {
       res.sendFile('index.html', {root: __dirname });
});

 app.post('/startRecurringNotifications', (req, res) => {
 console.log('setRecurring notifications');
 startNotification();
 res.sendStatus(200);
});

 app.post('/stopRecurringNotifications', (req, res) => {
      console.log('stop recurring notifications');
      clearInterval(intervalObj);
      res.sendStatus(200);
 });


 app.post('/subscription', (req, res) => {
     fakeDatabase.push(req.body);
     console.log(fakeDatabase);
     res.sendStatus(200);

  });

  app.post('/sendNotification', (req, res) => {
     console.log(req.body);
     const notificationPayload = {
       notification: {
           title: req.body.title,
           body: req.body.body,
           icon: 'assets/icons/icon-512*512.png',
   }};
   

   console.log("notificationpayload");
   const promises = [];
   fakeDatabase.forEach(subscription => {
   console.log(JSON.stringify(notificationPayload));
   promises.push(webpush.sendNotification(subscription, JSON.stringify(notificationPayload)));
 });
    Promise.all(promises).then(() => res.sendStatus(200));
 });

  var intervalObj;

  function startNotification() {
        intervalObj = setInterval(function(){
         const notificationPayload = {
         notification: {
            title: 'New Notification',
            body: 'This is notification body',
            icon: 'assets/icons/icon-512*512.png',
   }};

    fakeDatabase.forEach(subscription => {
    console.log("sending notifications");
    console.log(subscription);
    webpush.sendNotification(subscription, JSON.stringify(notificationPayload));
  });
 }, 5000);
}

 

File: index.html

 <!DOCTYPE html>
 <html lang="en">
 <head>
 <meta charset="UTF-8">
 <title>Notifications Backend Portal Page</title>
 <script src="https://ajax.googleapis.com/ajax/libs/jquery/3.4.1/jquery.min.js"></script>
 <script>
    $(function() {
        $.ajaxSetup({
            headers: {
              'Content-Type': 'application/json',
              'Accept': 'application/json'
          }
     });

   $('#btn1').on('click', function() {
        console.log("set recurring notifications");

         $.post('/startRecurringNotifications', function(data){
            console.log("successfully set the data");
            console.log(data);
        });
   });

   $('#btn2').on('click', function() {
         console.log("stop recurring notifications");
         $.post('/stopRecurringNotifications', function(data){
              console.log("stop recurring notifications ");
              console.log(data);
         });
    });

    $('#sendMessage').on('click', function() {
         console.log("send message");

        var reqBody = {};
        reqBody.title = $('#msgTitle').val();
        reqBody.body = $('#msgData').val();
        var bodyJson= JSON.stringify(reqBody);

        $.ajax({
           type: "POST",
           dataType: 'application/json',
            url: 'sendNotification',
            data: bodyJson,
         });
   });
});
</script>
</head>
<body>
<div>
<h2>Recurring Notifications for every 10 seconds</h2>
<button id="btn1" style="display: inline-block;">Start Notifications</button>
<button id="btn2" style="display: inline-block;">Stop Notifications</button>
</div>
<div>

<h2>Send customized message to user</h2>
<input type="textbox" id="msgTitle" placeholder="Enter the message title"></input><br/><br/>
<textarea id="msgData" rows="2" cols="50" placeholder="Enter the message data"></textarea>
<button id="sendMessage" style="display:block;">Send</button>
</div>
</body>
</html>


We are going to create two services, one is to send customized message, other for recurring notifications. Create html page to have notification backend service to manage the message sending to different users. Html page will look like below. In the text box we give the message tile and message body to send the message. Backend service is started with following command.

  node server.js

Recurring notifications is like if we start notification, it enables recurring notifications flag so it would be sending the messages in constant time period to the client.

 

Below video will show how the start and stop of recurring notifications works.

Sponsored:
To find embedded technology information about MCU, IoT, AI etc Check out embedkari.com.


   

Nagappan is a techie-geek and a full-stack senior developer having 10+ years of experience in both front-end and back-end. He has experience on front-end web technologies like HTML, CSS, JAVASCRIPT, Angular and expert in Java and related frameworks like Spring, Struts, EJB and RESTEasy framework. He hold bachelors degree in computer science and he is very passionate in learning new technologies.

Subscribe to our newsletter.

We will send mail once in a week about latest updates on open source tools and technologies. subscribe our newsletter



Related Articles

Angular Service Workers Usage Guide

  • angular service-worker offline-app

Web developers come across scenarios like web application completely breaks when workstation goes offline. Likewise to get into our application, every time we need to open a browser and then access it. Instead if it is in app, it will be easy to access for end-user. Push notifications similar to email client need to be done through web application. All these are addressed by a magic called service worker.

Read More


Getting Started on Angular 7

  • angular ui-ux front-end-framework

Angular is a platform for building responsive web, native desktop and native mobile applications. Angular client applications are built using HTML, CSS and Typescript. Typescript is a typed superset of Javascript that compiles to plain Javascript. Angular core and optional modules are built using Typescript. Code has been licensed as MIT License.

Read More


JHipster - Generate simple web application code using Spring Boot and Angular

  • jhipster spring-boot angular web-application

JHipster is one of the full-stack web app development platform to generate, develop and deploy. It provides the front end technologies options of React, Angular, Vue mixed with bootstrap and font awesome icons. Last released version is JHipster 6.0.1. It is licensed under Apache 2 license.

Read More


Scene.js - Library to Create Timeline-Based Animation

  • scenejs css timeline javascript animation motion

Scene.js is a JavaScript timeline-based animation library for creating animation websites. As an animated timeline library, it allows you to create a chronological order of movements and positions of objects.

Read More


Univention Corporate Server - An open source identity management system

  • ucs identity-management-system

Univention Corporate Server is an open source identity management system, an IT infrastructure and device management solution and an extensible platform with a store-like App Center that includes tested third party applications and further UCS components: This is what Univention combines in their main product Univention Corporate Server, a Debian GNU/Linux based enterprise distribution. This article provides you the overview of Univention Corporate Server, its feature and installation.

Read More



React Patent Clause Licensing issue. Is it something to worry?

  • react react-license facebook

React libraries from Facebook is one of the most used UI libraries. It is competitive to AngularJS. There are many open source UI components or frameworks available but mostly people narrow down to two choices Angular / React. Recently Facebook has updated React license and added a patent clause which makes companies to worry and rethink whether to use React or not.

Read More