Добавление тегов скриптов в шаблон углового компонента

Angular2 удаляет <script> теги автоматически из шаблонов, чтобы остановить людей, использующих эту функцию как "бедняга" погрузчик.

проблема здесь в том, что теги скриптов в настоящее время имеют больше применений, чем просто загрузка кода или других файлов скриптов. Существует вероятность того, что дальнейшая функциональность вокруг <script> теги будут введены в будущем.

одно текущее использование-JSON-LD, который принимает формат

<script type="application/ld+json">
{
    "@context":"http://schema.org",
    "@type":"HealthClub",
    ...
}
</script>

обыкновенно предлагаемая работа - это динамически добавить теги script к документу через ngAfterViewInit крюк, но это, очевидно, не правильная практика ng2 и не будет работать на стороне сервера, что JSON-LD, очевидно, должен быть в состоянии сделать.

есть ли другие обходные пути, которые мы можем использовать для включения <script> теги в шаблонах angular2 (даже если тег инертен в браузере) или это случай слишком самоуверенного фреймворка? Какие другие решения могут существовать, если это ситуация не может быть решена в angular2?

4 ответов


может быть, немного поздно на вечеринку здесь, но так как вышеуказанные ответы не работают хорошо с угловой ССР (например,document is not defined на стороне сервера или document.createElement is not a function), я решил написать версию, которая работает для Angular 4+,в контексте сервера и браузера:

Реализация Компонента

import { Renderer2, OnInit, Inject } from '@angular/core';
import { DOCUMENT } from '@angular/platform-browser';

class MyComponent implements OnInit {

    constructor(private _renderer2: Renderer2, @Inject(DOCUMENT) private _document) {

    }

    public ngOnInit() {

        let s = this._renderer2.createElement('script');
        s.type = `application/ld+json`;
        s.text = `
            {
                "@context": "https://schema.org"
                /* your schema.org microdata goes here */
            }
        `;

        this._renderer2.appendChild(this._document.body, s);
    }
}

Реализация Сервиса

Примечание: службы не могут использовать Renderer2 напрямую. Фактически, элемент рендеринга is предполагается, что выполняется компонентом. Однако вы можете оказаться в ситуации, когда вы хотите автоматизировать создание JSON-LD script теги на странице. Ситуация может заключаться в вызове такой функции в событиях изменения навигации по маршруту. Поэтому я решил добавить версию, которая работает в Service контексте.

import { Renderer2, Inject } from '@angular/core';
import { DOCUMENT } from '@angular/platform-browser';

class MyService {

    constructor(@Inject(DOCUMENT) private _document) {

    }

    /**
     * Set JSON-LD Microdata on the Document Body.
     *
     * @param renderer2             The Angular Renderer
     * @param data                  The data for the JSON-LD script
     * @returns void
     */
    public setJsonLd(renderer2: Renderer2, data: any): void {

        let s = renderer2.createElement('script');
        s.type = `application/ld+json`;
        s.text = `${JSON.stringify(data)}`;

        renderer2.appendChild(this._document.body, s);
    }
}

нет способа Angular2 добавления тега скрипта в шаблон.

используя require(...) для загрузки внешних скриптов из класса components был упомянут как обходной путь (сам не пробовал)

для динамического добавления тега script использовать

constructor(private elementRef:ElementRef) {};

ngAfterViewInit() {
  var s = document.createElement("script");
  s.type = "text/javascript";
  s.src = "http://somedomain.com/somescript";
  this.elementRef.nativeElement.appendChild(s);
}

см. также angular2: включая скрипты JS третьей стороны в компоненте


на самом деле Нет Angular2 путем добавления тега к шаблону. но вы можете сделать некоторые фишка в первую очередь вы импортируете AfterViewInit и ElementRef из angular2 вот так:

import {Component,AfterViewInit,ElementRef} from 'Angular2/core';

затем вы будете реализовывать их в своем классе так:

export class example1 implements AfterViewInit{}

и вот очень простой javascript DOM трюк, который вы собираетесь сделать

 export class example1 implements AfterViewInit{
 ngAfterViewInit()
 {
  var s=document.createElement("script");
  s.type="text/javascript";
  s.innerHTML="console.log('done');"; //inline script
  s.src="path/test.js"; //external script
 }
}

следующие работы с угловым 5.2.7:

необходимый импорт являются следующими:

import { Inject, AfterViewInit, ElementRef } from '@angular/core';
import { DOCUMENT } from '@angular/common';

Реализовать AfterViewInit:

export class HeroesComponent implements AfterViewInit {

если ваш компонент реализует более одного интерфейса, разделите их запятыми; например:

export class HeroesComponent implements OnInit, AfterViewInit {

передайте приведенные ниже аргументы конструктору:

constructor(@Inject(DOCUMENT) private document, private elementRef: ElementRef) { }

добавить ngafterviewinit метод просмотра жизненного цикла:

ngAfterViewInit() {
    const s = this.document.createElement('script');
    s.type = 'text/javascript';
    s.src = '//external.script.com/script.js';
    const __this = this; //to store the current instance to call 
                         //afterScriptAdded function on onload event of 
                         //script.
    s.onload = function () { __this.afterScriptAdded(); };
    this.elementRef.nativeElement.appendChild(s);
  }

добавить элемент afterScriptAdded функция.

эта функция будет вызвана после успешной загрузки внешнего скрипта. Таким образом, свойства или функции, которые вы хотите использовать из внешнего js, будут доступны в теле этой функции.

 afterScriptAdded() {
    const params= {
      width: '350px',
      height: '420px',
    };
    if (typeof (window['functionFromExternalScript']) === 'function') {
      window['functionFromExternalScript'](params);
    }
  }