1

In angular 2 one can load CSS styles depending on the component. However, there is no corresponding way to load script files. I am currently loading all scripts on the base page of my single page applications but that results in optimization issues.

What is the advised way of loading scripts for an Angular 2/4 component.

2
  • 1
    what scripts ? scripts cannot be used with specific components it has to be in index.html Commented Jul 25, 2017 at 5:09
  • If you need to load third party JS scripts or libs try and embedd that in your application instead of using it in index.html here is a link Commented Jul 25, 2017 at 6:03

2 Answers 2

1

You can load multiple scripts dynamically like this in your component.ts file:

 loadScripts() {
    const dynamicScripts = [
     'https://platform.twitter.com/widgets.js',
     '../../../assets/js/dummyjs.min.js'
    ];
    for (let i = 0; i < dynamicScripts.length; i++) {
      const 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);
    }
  }

and call this method inside the constructor,

constructor() {
    this.loadScripts();
}

Note : For more scripts to be loaded dynamically, add them to dynamicScripts array.

Sign up to request clarification or add additional context in comments.

Comments

1

Well you can load script dynamically in any component.

Here is the solution :

  1. Create a service in which you'll have js file.

    // script.store.ts
    
    interface Scripts {
      name: string;
      src: string;
    }
    
    export const ScriptStore: Scripts[] = [
      { name: 'moment', src: 'https://cdnjs.cloudflare.com/ajax/libs/moment.js/2.14.1/moment.min.js' },
      { name: 'datatables', src: 'https://cdn.datatables.net/v/dt/dt-1.10.12/datatables.min.js' }
    ];
    
  2. Now create a service that will load & return the status of the script.

    // script.service.ts
    
    import { Injectable } from '@angular/core';
    import { ScriptStore } from './script.store';
    
    declare var document: any;
    declare var jQuery: any;
    
    @Injectable()
    export class Script {
      public scripts: any = {};
    
      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);
          }
        });
      }
    
      constructor() {
        ScriptStore.forEach((script: any) => {
          this.scripts[script.name]={
            loaded: false,
            src: script.src
          };
        });
      }
    }
    
  3. Now you just need to import & call the service.

    // import
    import {Script} from './script.service'; // specify the path where you have created the service
    
    // Now call service
    
    ngAfterViewInit() {
      this._script.load('datatables')
        .then((data:any )=>{
          console.log(data,'script loaded')
        })
        .catch((error)=>{
        });
    }
    

It will dynamically add the script of 'datatables'.

This only serves your purpose but also it will load only where it is necessary.

2 Comments

Do you have a working plnkr of this code? I've tried it and I get an error that it can't find _script.load.
Don't have the plnkr but I got you.It seems you haven't defined the script in the constructor. Here is the example- constructor( public _script: Script ) { } This will resolve your error.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.