wake-up-neo.net

Hinzufügen von Skript-Tags in Angular Komponentenvorlage

Angular2 entfernt automatisch <script> - Tags aus Vorlagen, um zu verhindern, dass Benutzer diese Funktionalität als "Poor's Man" -Lader verwenden.

Das Problem hierbei ist, dass Skript-Tags derzeit mehr Verwendung finden als nur das Laden von Code oder anderen Skriptdateien. Es besteht die Möglichkeit, dass in Zukunft weitere Funktionen rund um <script> - Tags eingeführt werden.

Eine aktuelle Verwendung ist JSON-LD, das das Format annimmt

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

Eine häufig empfohlene Problemumgehung besteht darin, dem Dokument über den Hook ngAfterViewInitdynamisch Skript-Tags hinzufügen zuzuweisen. Dies ist jedoch offensichtlich nicht die richtige Vorgehensweise für ng2 und funktioniert nicht serverseitig, was JSON-LD betrifft muss natürlich können.

Gibt es andere Problemumgehungen, die wir verwenden können, um <script> - Tags in angle2-Vorlagen einzuschließen (auch wenn das Tag im Browser inert ist), oder ist das Framework in diesem Fall zu eigensinnig? Welche anderen Lösungen gibt es möglicherweise, wenn diese Situation in angle2 nicht gelöst werden kann?

35
Ian Belcher

Vielleicht ein bisschen zu spät zur Party hier, aber da die obigen Antworten nicht gut mit Angular SSR (zB document is not defined Serverseitig oder document.createElement is not a function) Funktionieren, Ich habe beschlossen, eine Version zu schreiben, die für Angular 4+, sowohl im Server- als auch im Browserkontext funktioniert:

Komponentenimplementierung

import { Renderer2, OnInit, Inject } from '@angular/core';
import { DOCUMENT } from '@angular/common';

class MyComponent implements OnInit {

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

    public ngOnInit() {

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

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

Service-Implementierung

HINWEIS: Dienste können Renderer2 Nicht direkt verwenden. Tatsächlich ist das Rendern eines Elements soll von einer Komponente durchgeführt werden. Möglicherweise befinden Sie sich jedoch in einer Situation, in der Sie die Erstellung von JSON-LD-Tags script auf einer Seite automatisieren möchten. Beispielsweise könnte eine Situation darin bestehen, eine solche Funktion bei Routennavigationsänderungsereignissen aufzurufen. Daher habe ich beschlossen, eine Version hinzuzufügen, die in einem Service -Kontext funktioniert.

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

/**
 * Use a Service to automate creation of JSON-LD Microdata.
 */
class MyService {

    constructor(
        @Inject(DOCUMENT) private _document: 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 script = renderer2.createElement('script');
        script.type = 'application/ld+json';
        script.text = `${JSON.stringify(data)}`;

        renderer2.appendChild(this._document.body, script);
    }
}
34
Nicky

Es gibt keine Angular2-Methode zum Hinzufügen eines Skript-Tags zu einer Vorlage.

Als Workaround wurde die Verwendung von require(...) zum Laden externer Skripte aus der Komponentenklasse erwähnt (habe es selbst nicht ausprobiert).

Verwenden Sie zum dynamischen Hinzufügen eines Skript-Tags

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);
}

Siehe auch angle2: js-Skripte von Drittanbietern in Komponente einschließen

16

Folgendes funktioniert mit Angular 5.2.7:

Die erforderlichen Importe sind:

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

Implementiere AfterViewInit:

export class HeroesComponent implements AfterViewInit {

Wenn Ihre Komponente mehrere Schnittstellen implementiert, trennen Sie diese durch Kommas. beispielsweise:

export class HeroesComponent implements OnInit, AfterViewInit {

Übergeben Sie die folgenden Argumente an den Konstruktor:

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

Fügen Sie die Methode ngAfterViewInit für den Ansichtslebenszyklus hinzu:

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);
  }

Fügen Sie die afterScriptAdded-Mitgliedsfunktion hinzu.

Diese Funktion wird aufgerufen, nachdem das externe Skript erfolgreich geladen wurde. Auf die Eigenschaften oder Funktionen, die Sie von externen js verwenden möchten, wird im Hauptteil dieser Funktion zugegriffen.

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

Eigentlich Es gibt keine Möglichkeit, Angular2 einem Template ein Skript-Tag hinzuzufügen. aber du kannst etwas tun trickzuallererst du importierst AfterViewInit und ElementRef aus angle2 wie folgt:

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

dann du wirst sie in deiner Klasse so implementieren:

export class example1 implements AfterViewInit{}

und hier ist ein sehr einfacher Javascript-Dom-Trick, den du machen wirst

 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
Mohsen M. Galal