Incorporating OneSignal into Angular for Seamless Notifications

I'm in the process of incorporating OneSignal into my Angular 2 application for push notifications. Initially, I successfully implemented a HelloWorld app using basic HTML. However, when attempting to integrate it into my Angular app, users are not being created or registered, and therefore cannot receive any notifications.

Highlighted Code:

index.html

<html>

<head>
  <meta charset="utf-8">
  <title>My Angular App</title>
  <base href="/">
  <meta name="viewport" content="width=device-width, initial-scale=1">
  <link rel="icon" type="image/x-icon" href="favicon.ico">
  <head>
    <link rel="manifest" href="/manifest.json">
  <script src="https://cdn.onesignal.com/sdks/OneSignalSDK.js" async></script>
  <script>
    var OneSignal = window.OneSignal || [];
    console.log("Initializing OneSignal");
    OneSignal.push(["init", {
      appId: "xxx-xxx-xxx-xxx-xxx",
      autoRegister: false,
      allowLocalhostAsSecureOrigin: true,
      notifyButton: {
        enable: true
      }
    }]);
    console.log('OneSignal Initialized');
    OneSignal.push(function () {
      console.log('Registered For Push');
      OneSignal.getUserId().then(function (userId) {
      console.log("User ID is", userId);
      });
    });
  </script>
  </head>
</head>

<body>
  <app-root>
    <div class="wrap">
      <div class="loading outer">
        <div class="loading inner"></div>
      </div>
    </div>
  </app-root>
</body>

</html>

The user ID consistently returns as null.

I have verified the following:

  • App ID is accurate
  • Browser notification permissions are set to allow

Queries:

  • Is there a method to execute all initialization processes inside a component, such as within the ngOnInit() method?
  • How can one register for push notifications when a user clicks on a button within my component rather than utilizing the bell icon? (Disabling the notifyButton option will hide the bell icon)

P.S: Tested on Chrome using Angular CLI (Did not function with Firefox or Safari)

Answer №1

It appears that I fell into the trap of skimming through the documentation rather than thoroughly reading it.

After tweaking the code a bit, I managed to get it to work as intended.

index.html

<html>

<head>
  <meta charset="utf-8">
  <title>My Angular App</title>
  <base href="/">
  <meta name="viewport" content="width=device-width, initial-scale=1">
  <link rel="icon" type="image/x-icon" href="favicon.ico">
  <head>
    <link rel="manifest" href="/manifest.json">
  <script src="https://cdn.onesignal.com/sdks/OneSignalSDK.js" async='async'></script>
    <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/animate.css/3.5.2/animate.min.css">
  </head>
</head>

<body>
  <app-root>
    <div class="wrap">
      <div class="loading outer">
        <div class="loading inner"></div>
      </div>
    </div>
  </app-root>
</body>

</html>

app.component.ts

export class AppComponent implements OnInit {
    .
    .
    .
    .
    ngOnInit() {
    var OneSignal = window['OneSignal'] || [];
    console.log("Init OneSignal");
    OneSignal.push(["init", {
      appId: "xxx-xxx-xxx-xxx",
      autoRegister: false,
      allowLocalhostAsSecureOrigin: true,
      notifyButton: {
        enable: false
      }
    }]);
    console.log('OneSignal Initialized');
    OneSignal.push(function () {
      console.log('Register For Push');
      OneSignal.push(["registerForPushNotifications"])
    });
    OneSignal.push(function () {
      // Occurs when the user's subscription changes to a new value.
      OneSignal.on('subscriptionChange', function (isSubscribed) {
        console.log("The user's subscription state is now:", isSubscribed);
        OneSignal.getUserId().then(function (userId) {
          console.log("User ID is", userId);
        });
      });
    });
    }
    .
    .
    .
}

A few key points to remember:

  • Make sure to listen for the subscriptionChange event and retrieve the user id
  • The subscriptionChange event is triggered when the user manually disables notifications in the browser.
  • Setting autoRegister: false, will not prompt the 'Allow'/'Deny' option. You will need to call registerForPushNotifications to trigger the prompt. This can be useful for triggering push notification prompts on specific actions like button clicks.

EDIT 2018

I have created a utility class that I utilize in all my Angular projects to streamline the implementation of OneSignal without unnecessary repetition of code.

https://gist.github.com/PsyGik/54a5e6cf5e92ba535272c38c2be773f1

Answer №2

To easily integrate One Signal into your project, simply insert the provided script into your index.html

<!DOCTYPE html>
<html lang="en>
  <head>
    <meta charset="utf-8" />
    <meta content="text/html; charset=utf-8" http-equiv="Content-Type" />
    <meta
      content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no"
      name="viewport"
    />

    ...
    ...

    <link rel="manifest" href="/manifest.json" />
    <script src="https://cdn.onesignal.com/sdks/OneSignalSDK.js" async=""></script>
    <script>
      var OneSignal = window.OneSignal || [];
      OneSignal.push(function() {
        OneSignal.init({
          appId: 'xxx-xxxx-xxxxx',
        });
      });
    </script>

    ...

Include the following in your angular.json


    ...
    "architect": {
        "build": {
          "builder": "ngx-build-plus:build",
          "options": {
            "outputPath": "dist/browser",
            "index": "src/index.html",
            "main": "src/main.ts",
            "polyfills": "src/polyfills.ts",
            "tsConfig": "src/tsconfig.app.json",
            "assets": [
              "src/favicon.ico",
              "src/favicon.png",
              "src/manifest.json", <-- this 
              "src/OneSignalSDKUpdaterWorker.js", <-- this 
              "src/OneSignalSDKWorker.js", <-- and finally this one
              "src/assets"
            ],
            "styles": [ 
              "src/styles.scss"
            ],
            "stylePreprocessorOptions": {
              "includePaths": ["src/assets/sass"]
            },
            "scripts": []
          },
          ...

Remember to place the manifest and the two *.js files in /src/*

After publishing it to your server, rather than localhost:4200, it should start working smoothly. This method worked for me, hopefully it helps you too!

Similar questions

If you have not found the answer to your question or you are interested in this topic, then look at other similar questions below or use the search

Upon executing the `npm start` command, the application experiences a crash

When I tried following the steps of the Angular quickstart guide, I encountered some errors after running "npm start". Here are the errors displayed: node_modules/@angular/common/src/directives/ng_class.d.ts(46,34): error TS2304: Cannot find name 'Se ...

Beware of the 'grid zero width' alert that may appear when utilizing ag-Grid's sizeColumnsToFit() function on multiple ag-Grids that are shown within a tab menu

Encountering a warning message when resizing ag-Grid and switching between tabs. The warning reads: ag-Grid: tried to call sizeColumnsToFit() but the grid is coming back with zero width, maybe the grid is not visible yet on the screen? A demo of this ...

Experience the magic of live streaming with our cutting-edge technology bundle featuring RTSP streaming, AspNet 5 API integration, FFM

Description: I am working on an API (ASP.Net 5) that connects to an IP Camera through RTSP. The camera sends a h264 stream converted with ffmpeg as an m3u8 stream, which is then returned to the Angular client in the following manner: public async Task< ...

One way to ensure a necessary check on the mat-expansion-panel

Currently, I am working on a form that includes an upload panel (mat-expansion-panel) for uploading documents. My goal is to indicate that this panel is required by adding an asterisk (*) next to it. While I know how to add the asterisk to <textarea&g ...

Mastering Angular2: Leveraging TypeScript's Power to Unleash JavaScript ES6 Syntax with

I am having trouble implementing a translation feature using the ng2-translate pipe in my Angular2/Ionic2 app, which is entirely written in JavaScript ES6. However, I have encountered an issue during the setup phase. The code snippets I have found on the ...

What is the best way to obtain a signed cookie in aws-sdk-js-v3?

I am looking to utilize signed cookies for accessing private content stored on S3 using CloudFront for CDN. I am struggling to identify the appropriate commands to generate signed cookies in aws-sdk-js-v3. According to the updated SDK documentation, it sh ...

The landscape of type definitions is evolving within TypeScript

Would someone please clarify why this is happening? Is it a bug or did I overlook something? function checkString<T>(arg:T):boolean { return (typeof(arg)==='string') ? true : false; } let myEcho; myEcho = checkString; let myInt :numb ...

What is the best way to change a blob into a base64 format using Node.js with TypeScript?

When making an internal call to a MicroService in Node.js with TypeScript, I am receiving a blob image as the response. My goal is to convert this blob image into Base64 format so that I can use it to display it within an EJS image tag. I attempted to ach ...

Remember to store a reference of ViewChild within the parent class

In order to access my graph in a child component using @ViewChild, which is declared in the parent class, I am looking for a way to avoid having to create a new variable for each child class instance. Parent class: import { Component, ViewChild} from &ap ...

A Comparison of Performance between If and Filter Operators in RxJS

Let's take a look at an example using RxJS. Type X: [utilizing filter] this.userService.afAuth.authState .pipe(filter(user => !!user)) .subscribe( _ => this.router.navigate(["/anything"]) ) Type Y: [utilizing if statement] this.u ...

Mapping JSON to interface in Angular 7: A step-by-step guide

I am currently working with angular7 and I have a requirement to map a json object to my interface. My goal is to create a function that can accurately map the fields of the json object to the corresponding properties in the interface. Additionally, if the ...

Configure Typescript to skip errors for a specific file

Is there a way to suppress TypeScript errors for specific files using the tsconfig.json file? I am aware of the exclude property mentioned on the TypeScript website, but that's not exactly what I'm looking for. As it's explained: If a fil ...

Prevent the array from altering its values

I am utilizing a mock-service that is configured in the following way: import { Article } from "./article"; export const ARTICLES: Article[] = [ new Article( 1, 'used', 5060639120949, 'Monster Energy& ...

When converting to TypeScript, the error 'express.Router() is not defined' may

Currently, I am in the process of converting my express nodejs project from JavaScript to TypeScript. One of the changes I've made is renaming the file extension and updating 'var' to 'import' for "require()". However, there seems ...

The 'initializeOnMount' property is a necessary requirement within the definition of the 'MoralisProviderInitializedProps' type

I encountered an unexpected issue with the code below: Type '{ children: Element; appId: string | undefined; serverUrl: string | undefined; }' is not compatible with type 'IntrinsicAttributes & MoralisProviderProps'. The property ...

Issues with Angular event binding not meeting the expected functionality

I'm currently working on a form that includes fields for usernames and email addresses. Alongside these, I have a separate field where I want the text input by the user to be displayed. I'm facing an issue with event binding within the form – i ...

Organizing JSON responses with pg-promise, representing related keys as nested objects

In my latest project, I am developing a basic REST platform using Node.JS and PostgreSQL. To access the database, I am utilizing pg-promise. The main objective is to create a simple ticketing system that includes users and tickets. Currently, my focus is o ...

Utilizing Angular to showcase information within a template

I'm delving into Angular and building my first component - a countdown feature. However, I'm facing a challenge when it comes to displaying the results on the template. I attempted using {{}}, but nothing seems to be happening. Thank you in adv ...

What is the best way to utilize the select all feature in Angular Material select components?

Is it possible for anyone to utilize the array data provided in the URL below? [{"columnName":"Column 1 - Type of Medication\n Number of Medications","selected":false},{"columnName":"Column 2 - Placebo&bsol ...

A guide to creating a TypeScript redux middleware class

As specified in the typescript definition for Redux, these interfaces must be implemented to create middleware: /* middleware */ export interface MiddlewareAPI<D extends Dispatch = Dispatch, S = any> { dispatch: D getState(): S } /** * A midd ...