Dynamically load external javascript file from Angular component

I had the same problem, but in my case, I was importing 10 libraries at the end of the html file, and these libraries have a lot of methods, listeners, events, and more, and in my case I didn't need to call a method specifically.

The example about what I had:

<!-- app.component.html -->

<div> 
 ...
</div>

<script src="http://www.some-library.com/library.js">
<script src="../assets/js/my-library.js"> <!-- a route in my angular project -->

As mentioned, it didn't work. Then, I find somehing that helped me: Milad response

  1. Remove the script calls in the app.component.html. You have to link these scripts in the app.component.ts file.

  2. In ngOnInit(), use a method to append the libraries, for example:

``

<!-- app.component.ts -->

export class AppComponent implements OnInit {
   title = 'app';
   ngOnInit() {
     this.loadScript('http://www.some-library.com/library.js');
     this.loadScript('../assets/js/my-library.js');
   }
  }

  public loadScript(url: string) {
    const body = <HTMLDivElement> document.body;
    const script = document.createElement('script');
    script.innerHTML = '';
    script.src = url;
    script.async = false;
    script.defer = true;
    body.appendChild(script);
  }
}

It functions for me. I use Angular 6, hope it helps.


Try to load external JavaScript on component load as below :

loadAPI: Promise<any>;

constructor() {        
    this.loadAPI = new Promise((resolve) => {
        this.loadScript();
        resolve(true);
    });
}

public loadScript() {        
    var isFound = false;
    var scripts = document.getElementsByTagName("script")
    for (var i = 0; i < scripts.length; ++i) {
        if (scripts[i].getAttribute('src') != null && scripts[i].getAttribute('src').includes("loader")) {
            isFound = true;
        }
    }

    if (!isFound) {
        var dynamicScripts = ["https://widgets.skyscanner.net/widget-server/js/loader.js"];

        for (var i = 0; i < dynamicScripts.length; i++) {
            let node = document.createElement('script');
            node.src = dynamicScripts [i];
            node.type = 'text/javascript';
            node.async = false;
            node.charset = 'utf-8';
            document.getElementsByTagName('head')[0].appendChild(node);
        }

    }
}

add loader.js to your assets folder then in your angular-cli.json

"scripts": ["./src/assets/loader.js",]

then add this to your typings.d.ts

 declare var skyscanner:any;

and you will be able to use it

  skyscanner.load("snippets","2");

I have done this code snippet

 addJsToElement(src: string): HTMLScriptElement {
    const script = document.createElement('script');
    script.type = 'text/javascript';
    script.src = src;
    this.elementRef.nativeElement.appendChild(script);
    return script;
  }

And then call it like this

this.addJsToElement('https://widgets.skyscanner.net/widget-server/js/loader.js').onload = () => {
        console.log('SkyScanner Tag loaded');
}

EDIT: With new renderer Api it can be written like this

constructor(private renderer: Renderer2){}

 addJsToElement(src: string): HTMLScriptElement {
    const script = document.createElement('script');
    script.type = 'text/javascript';
    script.src = src;
    this.renderer.appendChild(document.body, script);
    return script;
  }

StackBlitz