Skip to content

Instantly share code, notes, and snippets.

@sebastiandg7
Created June 21, 2018 20:27
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save sebastiandg7/a670d614699912f55e4d3668dbe7604f to your computer and use it in GitHub Desktop.
Save sebastiandg7/a670d614699912f55e4d3668dbe7604f to your computer and use it in GitHub Desktop.
Angular: dynamically load local or URL hosted JS scripts
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);
}
});
}
}
interface Scripts {
name: string;
src: string;
}
export const GOOGLE_MAPS = 'GOOGLE_MAPS';
export const RANGE_SLIDER = 'RANGE_SLIDER';
export const ScriptStore: Scripts[] = [
{name: GOOGLE_MAPS, src: 'https://maps.googleapis.com/maps/api/js?key=<api_token>'},
{name: RANGE_SLIDER, src: '../../../assets/js/ion.rangeSlider.min.js'}
];
// Usage example
// ===========================================================
// google-maps.service.ts
import { Injectable } from '@angular/core';
import { ScriptService } from '../scripts/script.service';
import { GOOGLE_MAPS } from '../scripts/script.store';
@Injectable({
providedIn: 'root'
})
export class GoogleMapsService {
constructor(private scriptService: ScriptService) { }
init(): Promise<any[]> {
return this.scriptService.load(GOOGLE_MAPS);
}
}
// ===========================================================
// my-component.component.ts
import { Component, OnInit } from '@angular/core';
import { GoogleMapsService } from '../../route/to/google-maps.service';
@Component({
selector: 'app-my-component',
templateUrl: './my-component.component.html',
styleUrls: ['./my-component.component.css']
})
export class MyComponent implements OnInit {
constructor(private googleMapsService: GoogleMapsService) { }
ngOnInit() {
this.googleMapsService.init().then(() => {
console.log(google.maps);
});
}
}
// ===========================================================
// If typings are not defined for the library you must
// install them from @types/your-library (if exists) if not,
// you must define them in your typing.d.ts
declare namespace google {
export var maps: any;
}
@sebastiandg7
Copy link
Author

sebastiandg7 commented Jun 21, 2018

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment