Search code examples
javascriptangulartypescriptangular2-services

Plain Javascript as Angular 2 service


I need to add a hosted third-party JavaScript file in an Angular 2 component. This file is updated anytime a change is made in the associated third-party vendors proprietary system, so I cannot simply pull down a copy, include it locally, and import it into the project.

Typically I would include this file at a top level in a script tag, and then simply use declare <windowvar>: any to get access to it. However in this case, since the component itself is trying to load the script, I cannot declare the window variable because it does not exist on the window object at the time the component is loaded, which generates an error.

I can load the script by manually adding a script tag, and that works, however I need access to the window variable it creates in order to use it properly. And I cannot simply use an interval to look for it because typescript throws a fit that <windowvariable> does not exist on object window.

Is there any way I can 1) Load the hosted JavaScript file inside the component, and 2) Get access to the window variable created by the loaded JavaScript file?


Solution

  • Update 1: Based on the comments, the previous solution will be not help you.

    You can do that by using OpaqueToken in Angular2

    1. Create a Token that is used to find an instance as below in a separate ts file.

    import { OpaqueToken } from '@angular/core'
    
    export let name_of_The_Token = new OpaqueToken('name_Of_The_Window_Object');
    

    2. In your App.module, you need to import and declare a variable that is the name of your window object which makes the Token as a angular2 service so that you can use properties, methods in that javascript file across your components.

    import { name_of_The_Token } from '/* file_Path */';
    declare let name_Of_The_Window_Object : any;  //below your import statements
    

    Step 3: Inject it to providers array of your module.

    { provide : name_of_The_Token , useValue : name_Of_The_Window_Object }
    

    Guidance to use this token in components

    1. Import the token just like any other service and @Inject from angular-core

       import { name_of_The_Token } from '/* file_Path */';
       import { Inject } from '@angular/core';
      
    2. In constructor of the component

       constructor(@Inject( name_of_The_Token ) private _serviceObject : any )       
      
    3. Any where in your component you can use the variables and methods of your javascript file as

       this._serviceObject.method1()
       this._serviceObject.variable1
       .....
      

    Note: One drawback is that you will not get intellisense.

    Overcoming it: If you are looking for intellisense you need to wrap the methods and variables inside an interface and use it in the type**(instead of any)** of your token as

    export interface myCustom {
          method1(args): return_Type;
          method2(args): void;
          .....
       }
    

    LIVE DEMO of ToasterService