8

Is there a correct way to invoke a JavaScript function from a component in Angular 2 (TypeScript) ?

Here is my component :

import { ElementRef, AfterViewInit }       from '@angular/core';

export class AppComponent implements AfterViewInit {

    constructor(private _elementRef: ElementRef) {
    }

    ngAfterViewInit() {
        /**
         * Works but i have this error :
         * src/app.component.ts(68,9): error TS2304: Cannot find name 'MYTHEME'.
         * src/app.component.ts(69,9): error TS2304: Cannot find name 'MYTHEME'.
         */
        MYTHEME.documentOnLoad.init(); 
        MYTHEME.documentOnReady.init();

        /**
         * Works without error, but doesn't seem like a right way to do it
         */
        var s = document.createElement("script");
        s.text = "MYTHEME.documentOnLoad.init(); MYTHEME.documentOnReady.init();";
        this._elementRef.nativeElement.appendChild(s);
    }
}

Calling the JavaScript function directly result in an compilation error, but the syntax in the "compiled" JavaScript file (app.component.js) is correct :

AppComponent.prototype.ngAfterViewInit = function () {
    MYTHEME.documentOnLoad.init();
    MYTHEME.documentOnReady.init();
};

The 2nd way (appendChild) works without error, but i don't think (altering the DOM from typescript/angular) is the correct way to do it.

I found this : Using a Javascript Function from Typescript I tried declaring the interface :

interface MYTHEME {
    documentOnLoad: Function;
    documentOnReady: Function;
}

But the TypeScript doesn't seem to recognize it (no error in the interface declaration).

Thanks

Edit :

Following the answer by Juan Mendes this is what i ended with :

import { AfterViewInit }       from '@angular/core';

interface MYTHEME {
    documentOnLoad: INIT;
    documentOnReady: INIT;
}
interface INIT {
    init: Function;
}
declare var MYTHEME: MYTHEME;

export class AppComponent implements AfterViewInit {

    constructor() {
    }

    ngAfterViewInit() {
        MYTHEME.documentOnLoad.init(); 
        MYTHEME.documentOnReady.init();
    }
}
Roham Rafii
  • 2,929
  • 7
  • 35
  • 49
Joshua
  • 627
  • 4
  • 9
  • 21

1 Answers1

7

You have to tell TypeScript about external (JavaScript) declarations using declare. See https://www.typescriptlang.org/docs/handbook/writing-declaration-files.html

interface MyTheme {
    documentOnLoad: Function;
    documentOnReady: Function;
}
declare var MYTHEME: MyTheme;

Or anonymously

declare var MYTHEME: {documentOnLoad: Function, documentOnReady: Function};
Ruan Mendes
  • 90,375
  • 31
  • 153
  • 217
  • @Joshua can you make little bit elaborate the steps, as am new to typescript, looking to invoke a js function from the external js file inside the components – balajivaishnav Dec 01 '16 at 08:00
  • 1
    @MBalajivaishnav My answer is not the place for you to ask unrelated questions. Please delete this comment and add a new question, we don't recycle questions here so that each question can have its own post so it can be most useful to others. – Ruan Mendes Dec 01 '16 at 09:35
  • @JuanMendes am not asking any unrelated question, am asking to elaborate the steps that's it, if I do ask a new question which will be duplicated hope you understand – balajivaishnav Dec 01 '16 at 09:40
  • 1
    @MBalajivaishnav My answer is not the place for you to ask Joshua a question even if you don't want to create a new post. His post already shows what it took to call a JS function from TS. If you still can't get your code to work, it's something else. Again, please create your own question showing what you have tried. SO is not for asking for code samples. It's for "I tried this (show code), but it didn't work. Here's what it did instead and here's the error message". You cannot convey that information through a comment. – Ruan Mendes Dec 01 '16 at 09:50
  • @JuanMendes Joshua has accepted your answer, which means it worked for him so I thought he would be the right person to ask my doubt, I did not ask him for any code snippets rather I have doubt in importing js file to angular 2 typescript file and creating interface for it, so I asked him to elaborate it little bit about that,I hope you are aware of the StackOverflow rules if I ask the same question it will be duplicated again redirected to this question, instead I asked here directly I don't find any issue in this – balajivaishnav Dec 01 '16 at 10:02
  • It will not be a duplicate if you post you follow my suggestions. I can guarantee you the likelyhood of getting an answer is much higher if you do post a proper question – Ruan Mendes Dec 01 '16 at 10:34