How to load external scripts dynamically in Angular?

lazy load external javascript
angular.json scripts not loading
angularjs call external javascript function
angularjs include js file
angular dynamically load script tag
assets javascript angular
angular with external javascript doesn't run after component change
import js file in angular

I have this module which componentize the external library together with additional logic without adding the <script> tag directly into the index.html:

import 'http://external.com/path/file.js'
//import '../js/file.js'

@Component({
    selector: 'my-app',
    template: `
        <script src="http://iknow.com/this/does/not/work/either/file.js"></script>
        <div>Template</div>`
})
export class MyAppComponent {...}

I notice the import by ES6 spec is static and resolved during TypeScript transpiling rather than at runtime.

Anyway to make it configurable so the file.js will be loading either from CDN or local folder? How to tell Angular 2 to load a script dynamically?

If you're using system.js, you can use System.import() at runtime:

export class MyAppComponent {
  constructor(){
    System.import('path/to/your/module').then(refToLoadedModule => {
      refToLoadedModule.someFunction();
    }
  );
}

If you're using webpack, you can take full advantage of its robust code splitting support with require.ensure :

export class MyAppComponent {
  constructor() {
     require.ensure(['path/to/your/module'], require => {
        let yourModule = require('path/to/your/module');
        yourModule.someFunction();
     }); 
  }
}

How to dynamically load external scripts in Angular – Lukas Jakob, How to dynamically load external scripts in Angular. In Angular applications sometimes it's necessary to use external libraries like Google Maps  The task is to load a JS code either from a CDN or JS file stored in the system dynamically at runtime in AngularJS i.e. JavaScript code should be loaded dynamically. For example, on a button press or on some event. Whenever we want to load the script file we would have to create an element of type “script” using document.createElement. We would then specify its src attribute to be the location of the script either CDN or a local js file.

You can use following technique to dynamically load JS scripts and libraries on demand in your Angular project.

script.store.ts will contain the path of the script either locally or on a remote server and a name that will be used to load the script dynamically

 interface Scripts {
    name: string;
    src: string;
}  
export const ScriptStore: Scripts[] = [
    {name: 'filepicker', src: 'https://api.filestackapi.com/filestack.js'},
    {name: 'rangeSlider', src: '../../../assets/js/ion.rangeSlider.min.js'}
];

script.service.ts is an injectable service that will handle the loading of script, copy script.service.ts as it is

import {Injectable} from "@angular/core";
import {ScriptStore} from "./script.store";

declare var document: any;

@Injectable()
export class ScriptService {

private scripts: any = {};

constructor() {
    ScriptStore.forEach((script: any) => {
        this.scripts[script.name] = {
            loaded: false,
            src: script.src
        };
    });
}

load(...scripts: string[]) {
    var promises: any[] = [];
    scripts.forEach((script) => promises.push(this.loadScript(script)));
    return Promise.all(promises);
}

loadScript(name: string) {
    return new Promise((resolve, reject) => {
        //resolve if already loaded
        if (this.scripts[name].loaded) {
            resolve({script: name, loaded: true, status: 'Already Loaded'});
        }
        else {
            //load script
            let script = document.createElement('script');
            script.type = 'text/javascript';
            script.src = this.scripts[name].src;
            if (script.readyState) {  //IE
                script.onreadystatechange = () => {
                    if (script.readyState === "loaded" || script.readyState === "complete") {
                        script.onreadystatechange = null;
                        this.scripts[name].loaded = true;
                        resolve({script: name, loaded: true, status: 'Loaded'});
                    }
                };
            } else {  //Others
                script.onload = () => {
                    this.scripts[name].loaded = true;
                    resolve({script: name, loaded: true, status: 'Loaded'});
                };
            }
            script.onerror = (error: any) => resolve({script: name, loaded: false, status: 'Loaded'});
            document.getElementsByTagName('head')[0].appendChild(script);
        }
    });
}

}

Inject this ScriptService wherever you need it and load js libs like this

this.script.load('filepicker', 'rangeSlider').then(data => {
    console.log('script loaded ', data);
}).catch(error => console.log(error));

Angular: Load External JavaScript File Dynamically, If you are creating a large scale app or an enterprise application using Angular 2​+, you have components or directives that require certain external JavaScript  In Angular applications sometimes it’s necessary to use external libraries like Google Maps, as in any other application as well. In this post I’ll show how to create a service for this job. The basic idea is to use. document.createElement('script') to add the script source and append it to the DOM head element.

This might work. This Code dynamically appends the <script> tag to the head of the html file on button clicked.

const url = 'http://iknow.com/this/does/not/work/either/file.js';

export class MyAppComponent {
    loadAPI: Promise<any>;

    public buttonClicked() {
        this.loadAPI = new Promise((resolve) => {
            console.log('resolving promise...');
            this.loadScript();
        });
    }

    public loadScript() {
        console.log('preparing to load...')
        let node = document.createElement('script');
        node.src = url;
        node.type = 'text/javascript';
        node.async = true;
        node.charset = 'utf-8';
        document.getElementsByTagName('head')[0].appendChild(node);
    }
}

Angular2: how to load external javascript file dynamically, I am trying to load an external library (Javascript) to an Angular2 component (​TypeScript). Angular2: how to load external javascript file dynamically Does the crop function work by itself (i.e. outside of angular)? Are there  Angular, being a SPA (Single Page Application), loads all of its scripts on initial page load. So if index.html contains any external JS scripts that are not required on all views, it might increase the latency time for the page to load completely, which is not the best practice in my opinion.

I have modified @rahul kumars answer, so that it uses Observables instead:

import { Injectable } from "@angular/core";
import { Observable } from "rxjs/Observable";
import { Observer } from "rxjs/Observer";

@Injectable()
export class ScriptLoaderService {
    private scripts: ScriptModel[] = [];

    public load(script: ScriptModel): Observable<ScriptModel> {
        return new Observable<ScriptModel>((observer: Observer<ScriptModel>) => {
            var existingScript = this.scripts.find(s => s.name == script.name);

            // Complete if already loaded
            if (existingScript && existingScript.loaded) {
                observer.next(existingScript);
                observer.complete();
            }
            else {
                // Add the script
                this.scripts = [...this.scripts, script];

                // Load the script
                let scriptElement = document.createElement("script");
                scriptElement.type = "text/javascript";
                scriptElement.src = script.src;

                scriptElement.onload = () => {
                    script.loaded = true;
                    observer.next(script);
                    observer.complete();
                };

                scriptElement.onerror = (error: any) => {
                    observer.error("Couldn't load script " + script.src);
                };

                document.getElementsByTagName('body')[0].appendChild(scriptElement);
            }
        });
    }
}

export interface ScriptModel {
    name: string,
    src: string,
    loaded: boolean
}

How to Load External JS Scripts Dynamically in AngularJS , The task is to load a JS code either from a CDN or JS file stored in the system dynamically at runtime in AngularJS i.e. JavaScript code should be loaded  I have this module which componentize the external library together with additional logic without TypeScript transpiling rather than at runtime. 67336/how-to-load-external-scripts-dynamically-in-angular

Yet another option would be to utilize scriptjs package for that matter which

allows you to load script resources on-demand from any URL

Example

Install the package:

npm i scriptjs

and type definitions for scriptjs:

npm install --save @types/scriptjs

Then import $script.get() method:

import { get } from 'scriptjs';

and finally load script resource, in our case Google Maps library:

export class AppComponent implements OnInit {
  ngOnInit() {
    get("https://maps.googleapis.com/maps/api/js?key=", () => {
        //Google Maps library has been loaded...
    });
  }
}

Demo

Load external js script dynamically in Angular 2 · Issue #21376 , I am building an application using angular 2, wherein I want some external javascript files to be loaded for some specific components and not  How to load external scripts dynamically in Angular? If you're using system.js, you can use System.import() at runtime. load external scripts in Angular

How to load external scripts dynamically in Angular?, Hello kartik,. You can use following technique to dynamically load JS scripts and libraries on demand in your Angular project. script.store.ts will contain the path  Dynamically Loading third-party(external) library (by dynamically adding script tag) Initially Loading External Library from CDN It is the easiest way to load external libraries from CDN. you just need to add script tag in the < head > section of index.html .

Angular - load external javascript dynamically, How to load external script to your Angular project, or how to reload external javascript to Angular project? So, for example, if you. It would make more sense to export that myCropper code as a function (like the one that is currently your event callback) from a dedicated module, which you'd then simply import and call on init -- no messing with script elements in the document head.

Lazy Loading External JavaScript Libraries in Angular, js as an example to show a generic way of lazy loading external JavaScript libraries. The goal is to get Angular to lazily load Quill JavaScript and  The benefit here is that although the page uses a lot of Angular components, the page can load initially with the bare minimum and then incur the payload cost when it is actually required.

Comments
  • Possible duplicate of ES6 variable import name in node.js?
  • It seems like I need to use module loader specifically in the component. Well, that's fine since System is the future of loader, I think.
  • TypeScript Plugin for Sublime Text does not happy with System in the TypeScript code: Cannot find name 'System' but no error during transpiling and running. Both Angular2 and System script file already added into index.html. Anyway to import the System and make the plugin happy?
  • but what if you are not using system.js!
  • @drewmoore I don't remember why I said so, require()/import should work fine as your answer now, +1
  • From what I can tell these options don't work for scripts on the internet, just for local files. This doesn't seem to answer the original question as asked.
  • This works brilliantly. Shaves over 1MB off initial load size - I have a lot of libraries!
  • Looks like I spoke too soon. This solution does NOT work in iOS Safari.
  • after loading the script check whether it's appending to head of your dom
  • Perhaps I'm not injecting correctly, but I'm getting this.script.load is not a function
  • Thanks. This works, but I am getting my script (a background animation) loaded in every other component. I want it to be loaded only on my first component (it is a login page). What can I do to achieve that? Thanks