Creating a singleton in TypeScriptWould you like to know how to declare a singleton in

My goal is to incorporate an already existing library into my TypeScript project. The library contains a singleton object that I want to declare and utilize.

For example, within the xyz.js file, the following object is defined:

var mxUtils = {
    /* some complex code */
    findNode: function(node, attr, value)
    {
        // more complex code here
        return node;
    }
};

There exists only one global instance of mxUtils during runtime as it is an external library. I prefer not to rewrite or reimplement the entire library in TypeScript.

I attempted to declare this singleton object but encountered difficulties.

This is the code snippet I tried to use to declare the Object globally:

In Utils.d.ts:

declare interface ImxUtils { 
    findNode(node:any, attr:string, value:string):any;
}

declare var mxUtils: ImxUtils;

Although my compiler accepted this declaration, mxUtils is undefined during runtime.

In main.ts:

// performing some operations
export class fancyComponent implements OnInit {
    // adding some magic...
    var tmpNode = mxUtils.findNode(aNode, aString1, aString2);    
}

Despite seeing a global mxUtils Object in my debugger, I am unable to access it within my fancyComponent export.

If anyone can provide assistance with this issue, it would be greatly appreciated.

Also, note that xyz.js has been referenced and is present.

Take for example:

xyz.js:

function mxEventObject(name)
{
//
}

mxEventObject.prototype.getName = function()
{
    return this.name;
};

In Utils.d.ts:

declare class mxEventObject {
    constructor(name: string);
    getName: () => string;
}

In main.ts:

export class fancyComponent implements OnInit {
    // including some more magic...
    var tmpEvent = new mxEventObject(aSampleString);
}

The above setup should work as intended.

Given the presence of a global object named mxUtils but my inability to access it within my fancyComponent export, I suspect there may be a scope issue at play here.

Answer №1

When working in Angular, it is best practice to utilize the Dependency Injection (DI) system for handling object creation and injection into components. To achieve this, you will need to create an angular service and include this service in the providers list within the AppModule component decorator.

mx-utils.service.ts

export class MxUtilsService {

  /* some fancy code */
  public findNode(node:any, attr:any, value:any) {
    // even more fancy code
    return node;
  }
}

app.module.ts

@NgModule({
  imports:      [ BrowserModule, FormsModule ],
  declarations: [ AppComponent ],
  bootstrap:    [ AppComponent ],
  providers: [MxUtilsService]
})
export class AppModule { }

app.component.ts

import { Component } from '@angular/core';
import { MxUtilsService } from './mx-utils.service';

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

  constructor(private _mxUtilsService: MxUtilsService) {
    console.log(this._mxUtilsService);
    console.log(this._mxUtilsService.findNode({node:1},'node',1));
  }
}

Any service added to the providers list in AppModule (root) is considered a singleton. MxUtilsService will be created once and remain the same object when injected into other components.

StackBlitz Demo

If your object is undefined, make sure to add xyz.js to the scripts list in .angular-cli.json.

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

Steps for utilizing Bazel to compile TypeScript

Calling all Bazel (Blaze) experts: I'm curious about the best method for integrating Bazel as a build system for cutting-edge web applications built in Typescript. Is there a preferred setup or perhaps a template that demonstrates this integration? T ...

Having trouble with React Hook Form controlled input and typing

My application utilizes the react-hook-forms library along with the office-ui-fabric-react framework. To integrate the framework inputs, I wrap the 3rd party component using the <Controller> element. The current setup is functional as shown below: ...

The issue I am facing is with the post_logout_redirect_uri not functioning properly when using localStorage in an OIDC Auth

authority: 'yyy', client_id: this.'yyy', redirect_uri: 'http://localhost:4200/login', response_type: 'token', scope: 'yyy', post_logout_redirect_uri: & ...

The attribute 'pixiOverlay' is not found in the property

Working on my Angular 8 project, I needed to display several markers on a map, so I chose to utilize Leaflet. Since there were potentially thousands of markers involved, I opted for Leaflet.PixiOverlay to ensure smooth performance. After installing and imp ...

What is the best way for me to access a certain web address?

I am working on setting up a routing mechanism in my Angular project, but I'm encountering a URL routing error. The application is unable to locate the specified URL. Below is the routing setup: navigation.ts { id: 'documentation-manag ...

Enhancing Material UI v4 Themes using TypeScript

I am attempting to implement my own custom palette option in the theme section, but I am struggling with how to do the augmentation part using TypeScript. So far, I have created a file named "material-ui.d.ts" and inside it, I only have: import { PaletteO ...

Activating `routerLinkActive` for multiple components

When working with Angular 2+, I have a navbar set up within an 'Articles' feature module like this: <li> <a routerLinkActive="active" routerLink="current">Current</a> </li> <li> <a router ...

Received an error stating, "0 arguments were provided when expecting 1-3" while attempting to run the ng build --prod command

I'm currently developing a navigation panel that displays hierarchy and child items when parent items are clicked: <div *ngFor="let t of temp(math.ceil(rr2.children.length/3)).fill(); let ei = index"> <!-- <div *ng ...

When trying to reload Angular 8 pages, encountering an error that reads "Cannot GET /login" and also receiving a notification stating the image '/favicon.ico' cannot be loaded due to a violation of

Encountering an issue with the error message "Cannot GET login/" appearing on the page body of my latest Angular 8 app. Despite attempting various solutions found on forums, I have been unable to resolve this error. Any suggestions or advice would be great ...

Dealing with client-side exceptions in a Next.js 13 application's directory error handling

After carefully following the provided instructions on error handling in the Routing: Error Handling documentation, I have successfully implemented both error.tsx and global-error.tsx components in nested routes as well as the root app directory. However, ...

Angular 2: The *ngFor directive is unable to locate a suitable differing framework

Below is the code for client.service.ts clients: Client[]; getClientList() { let headers = new Headers(); headers.append('Content-Type', 'application/json'); let authToken = localStorage.getItem('auth_token&apo ...

Angular auto suggest feature

I am working with a dropdown in Angular that contains JSON data. The data is stored in a List named options and I need to display the name field in the dropdown list. My current task involves implementing an autocomplete search feature for this dropdown. ...

How to disable the first option in an Angular 2 select dropdown

I'm working with a select component, and here is the code snippet I have: <select name="typeSelection" materialize="material_select" [(ngModel)]="trainingplan.type" > <option [ngValue] = "null" disabled selected>Please choose a ...

Generating formarray instances in Angular using data from MySQL records

I am currently working on a project where I need to populate formcontrols in formarray based on the data retrieved from a MySQL database. However, when I pass the success data from MySQL, I encounter an error that says "Cannot read property 'controls& ...

Angular and Webpack combined to output the build project to the specified output path

In the process of integrating my Angular client-side application with a server-side written in Spring, I am seeking a way to build the UI project and store it in the /target directory within the backend portion for easy installation using Maven. My uncer ...

Presenting SQL information in a hierarchical Angular grid for easy visualization

As a newcomer to Angular, I have a requirement to display data in a multilevel/hierarchical Angular Grid. The data is retrieved from a SQL Database using a query with arguments provided in the where clause. Some questions that come to mind are: Is there ...

I am trying to replace the buttons with a dropdown menu for changing graphs, but unfortunately my function does not seem to work with the <select> element. It works perfectly fine with buttons though

I am currently working on my html and ts code, aiming to implement a dropdown feature for switching between different graphs via the chartType function. The issue I am facing is that an error keeps popping up stating that chartType is not recognized as a ...

It's possible that the "device.interfaces" variable has not been defined

I am currently working on creating a USB driver in TypeScript using the libusb library to adjust my keyboard lighting. However, I encountered an issue where I received a 'possibly undefined' error when trying to retrieve the interface number. The ...

Showcasing a single JSON object in an Angular application

After receiving a Json object from an API, I attempted to display it in my component with no success. Below is the code snippet of my component: selector: 'app-links-page-detail', templateUrl: './links-page-detail.component.html', ...

Repurpose existing views within an Angular 2+ component

There are times when I want to reuse certain views (HTML code) within a component without creating a new component. It would look something like this: <div *ngIf="Fordestop"> <div class="divdesktop"></div> #insert-my-reuse-div-he ...