Меню ×
Динамическое добавление элемента script в Angular

Динамическое добавление элемента script в Angular

Не часто при разработке SPA приложения появляется задача с динамическим добавлением JS файла на страницу.

В данной статье рассмотрим несколько возможных способов динамического добавления script в Angular.

Динамическое добавление css link и js script

Добавление link и script нативным способом в JavaScript

	
// Добавление стилей
const link = document.createElement('link');
link.rel = 'stylesheet';
link.type = 'text/css';
link.href = 'https://stackpath.bootstrapcdn.com/bootstrap/4.1.3/css/bootstrap.min.css';
document.head.appendChild(link);

// Добавление скрипта
const script = document.createElement('script');
script.src = 'https://code.jquery.com/jquery-3.3.1.slim.min.js';
document.body.appendChild(script)
	

Певрый способ

Примитивный способ. Аналогичен нативной вставке скрипта в тело документа, описанным чуть выше.

	
constructor(
  @Inject(DOCUMENT) private document: Document,
  private renderer2: Renderer2
) {}

ngOnInit(): void {
  const textScript = this.renderer2.createElement('script');
  textScript.src = 'https://code.jquery.com/jquery-3.3.1.slim.min.js';
  this.renderer2.appendChild(this.document.body, textScript);

  const srcScript = this.renderer2.createElement('script');
  srcScript.type = 'text/javascript';
  srcScript.text = `
    (function() {
      console.log('Hello from Siberia!')
    }());
  `;
  this.renderer2.appendChild(this.document.body, srcScript);
}
	

Второй способ

Более продвинутый способ: завернуть в Promise.

	
ngOnInit() {
  this.loadScript('https://code.jquery.com/jquery-3.3.1.slim.min.js').then(
    () => this.loadTextScript(`
        setTimeout(() => {
          $( "#promise-based" ).html( "PromiseBasedComponent..." )
        }, 2000);
    `)
  );
}

loadTextScript(text: string) {
  return new Promise(resolve => {
    const script = this.renderer2.createElement('script');
    script.text = text;
    this.renderer2.appendChild(this.document.body, script);
    resolve();
  });
}

loadScript(url: string) {
  return new Promise((resolve, reject) => {
    const script = this.renderer2.createElement('script');
    script.src = url;
    script.onload = resolve;
    script.onerror = reject;
    this.renderer2.appendChild(this.document.body, script);
  });
}
	

Трейти способ

Способ с использование ReplaySubject в сервисе:

	
import { Injectable, Inject } from '@angular/core';
import { ReplaySubject, Observable } from 'rxjs';
import { DOCUMENT } from '@angular/common';

@Injectable()
export class LazyLoadingScriptService {
    _loadedLibraries: { [url: string]: ReplaySubject<any> } = {};

    constructor(@Inject(DOCUMENT) private readonly document: any) { }

    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.src = url;
        script.onload = () => {
            this._loadedLibraries[url].next();
            this._loadedLibraries[url].complete();
        };

        this.document.body.appendChild(script);

        return this._loadedLibraries[url].asObservable();
    }
}

      
/* Usage */
this.lazyLoadService.loadScript('/assets/scripts/some-script.js').subscribe(() => {
   // code
});
	

Похожие материалы

Angular зарекомендовал себя, как один из самых популярных фреймворков JavaScript. Его компонентная архитектура позволяет разработчику разделить приложение на небольшие многократно используемые фрагменты.

Создание директивы атрибута и использование класса Renderer2 в Angular

Создание кастомных событий и их обработчиков. Импорт свойств родительского компонента.

наверх