How to load external scripts dynamically in Angular?

前端 未结 15 750
被撕碎了的回忆
被撕碎了的回忆 2020-11-22 06:48

I have this module which componentize the external library together with additional logic without adding the

15条回答
  •  终归单人心
    2020-11-22 07:13

    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));
    

提交回复
热议问题