Skip to content

Instantly share code, notes, and snippets.

Embed
What would you like to do?
Remote Library service: Allows including external resources (scripts and CSS) to the DOM. If the library is already loaded just return the Observable.
import { Injectable, Inject } from '@angular/core';
import { ReplaySubject, Observable, forkJoin } from 'rxjs';
import { DOCUMENT } from '@angular/common';
@Injectable({
providedIn: 'root'
})
export class RemoteLibraryService {
// Ref.: https://codeburst.io/lazy-loading-external-javascript-libraries-in-angular-3d86ada54ec7
private _loadedLibraries: { [url: string]: ReplaySubject<any> } = {};
constructor(@Inject(DOCUMENT) private readonly document: any) {}
lazyLoadJsCss(scriptUrl: string, stylesUrl: string): Observable<any> {
return forkJoin([
this.loadScript(scriptUrl),
this.loadStyle(stylesUrl)
]);
}
loadScript(url: string): Observable<any> {
if (this._loadedLibraries[url]) {
return this._loadedLibraries[url].asObservable();
}
this._loadedLibraries[url] = new ReplaySubject();
const script = this.document.createElement('script');
script.type = 'text/javascript';
script.async = true;
script.src = url;
script.onload = () => {
console.log(`Script ${url} loaded...`);
this._loadedLibraries[url].next();
this._loadedLibraries[url].complete();
};
this.document.body.appendChild(script);
return this._loadedLibraries[url].asObservable();
}
loadStyle(url: string): Observable<any> {
if (this._loadedLibraries[url]) {
return this._loadedLibraries[url].asObservable();
}
this._loadedLibraries[url] = new ReplaySubject();
const style = this.document.createElement('link');
style.type = 'text/css';
style.href = url;
style.rel = 'stylesheet';
style.onload = () => {
console.log(`CSS styles ${url} loaded...`);
this._loadedLibraries[url].next();
this._loadedLibraries[url].complete();
};
const head = document.getElementsByTagName('head')[0];
head.appendChild(style);
return this._loadedLibraries[url].asObservable();
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment