Как заставить ваши Angular SPA хорошо взаимодействовать с устаревшими библиотеками

Большинство систем, которые предоставляют определенные часто используемые функции, также обеспечивают некоторую интеграцию. Скажем, эта библиотека графики и диаграмм, задокументированная на старом простом устаревшем JavaScript (‹ES5), со старым стилизованным кодом HTML & ‹script›, просто для включения гистограммы. Или какой-нибудь сайт, который позволяет посетителям покупать билеты на мероприятия, без API, без веб-компонентов, просто блок кода с «вставьте этот скрипт в свой код», который импортирует файл Javascript, файл CSS и встраивает iframe. Вы, наверное, видели это, а если нет, то когда-нибудь (поверьте мне ...)

Эта интеграция, в большинстве случаев, предназначена для не разработчиков, «включите этот код, и он будет работать», волшебство.

Но что, если вам нужно заставить эту интеграцию работать с вашим Angular SPA?

Недавно я боролся с библиотекой изменения размера iFrame, мне пришлось добавить сторонний блок кода, который включал iframe, файл js и файл CSS в компонент Angular. Чтобы улучшить UX, добавьте этот скрипт в заголовок вашего HTML…, и появится средство изменения размера iframe. Кстати, iframe абсолютно НИКАК улучшают UX, iframe просто выглядят как сообщение на экране.
Вкратце, я прочитал документацию, и ни одна из рекомендаций у меня не сработала.

Итак, вот что я сделал:

Динамически загружать все внешние необходимые файлы

Это будет добавление необходимых скриптов и CSS в DOM, но не путем вставки кода в шаблон компонента. Для этого мы воспользуемся сервисом:

Эта служба принимает URL-адрес сценария или файла CSS и добавляет его в HTML DOM. Включите его в качестве поставщика в файл app.module.ts, чтобы иметь единственный экземпляр службы и избежать загрузки файлов, если вы их уже загрузили.

Объявите глобальную переменную, чтобы обернуть скрипт

В вашем компоненте вам нужно будет объявить оболочку для стороннего скрипта, который вы пытаетесь включить. Есть небольшая надежда, что вы знакомы с внутренним устройством этого скрипта, поэтому вы можете определить интерфейс, который может позволить автозаполнение кода. Как обычно, мы просто будем использовать тип any.

Почему глобальный? Что ж, в компании, в которой я работаю, у нас есть некоторые проверки динамических форм, которые загружаются таким образом. У нас возникли проблемы с Safari, и объявление переменных объекта скрипта как глобальных решило проблему.

и наконец…

Используйте сторонний скрипт, как предложено

Теперь вы можете использовать сценарии, как показано в документации (код должен быть включен после того, как будут загружены сценарии, это между строками 34 и 36. Например:

// ...
    Promise.all(scriptArray).then(_ => {
      console.log('All scripts loaded');
      // These are not real methods, just placed them 
      // for illustrative purposes
      externalLibrary.loadData(this.data);
      externalLibrary.renderChart('barchart', 'chart-container');
      otherExternalLibrary.validateRoles();
   )};
// ...

Кстати, не копируйте и вставляйте код в GIST, я думаю, мне не хватает нескольких закрывающих скобок :)

А как насчет jQuery?

Да, еще есть люди, использующие jQuery. jQuery - другая история, однажды я попытался загрузить его таким образом и потерпел неудачу. Итак, мы выяснили, что единственный способ работы jQuery - это добавить его в последние строки файла polyfills.ts следующим образом:

import * as jQuery from 'jquery';
window['$'] = jQuery;

и вы сможете использовать $ как обычно.

Надеюсь, это поможет.