Aggiunta di tag di script nel modello di componente Angular2

Angular2 rimuove automaticamente i tag dai template per impedire che le persone utilizzino questa funzionalità come caricatore di “poor’s man” .

Il problema qui è che i tag script hanno attualmente più usi del semplice caricamento del codice o di altri file di script. C’è la possibilità che ulteriori funzionalità attorno ai tag vengano introdotte anche in futuro.

Un uso corrente è JSON-LD che prende il formato

  { "@context":"http://schema.org", "@type":"HealthClub", ... }  

Un ngAfterViewInit comunemente suggerito consiste nell’aggiungere dynamicmente tag di script al documento tramite l’hook ngAfterViewInit , ma ovviamente non è una pratica ng2 corretta e non funzionerà sul lato server, cosa che ovviamente JSON-LD deve essere in grado di fare.

Ci sono altre soluzioni alternative che possiamo usare per includere tag in modelli angular2 (anche se il tag è inerte all’interno del browser) o si tratta di un caso in cui il framework è troppo supponente? Quali altre soluzioni potrebbero esistere se questa situazione non può essere risolta in angular2?

    Forse un po ‘tardi per la festa qui, ma dal momento che le risposte di cui sopra non funzionano bene con Angular SSR (ad esempio il document is not defined lato server o document.createElement is not a function ), ho deciso di scrivere una versione che funziona per Angular 4+, sia nel contesto server che nel browser :

    Implementazione dei componenti

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

    Implementazione del servizio

    NOTA: i servizi non possono utilizzare direttamente Renderer2 . In effetti, l’elemento di rendering dovrebbe essere fatto da un componente . Tuttavia, potresti trovarti nella situazione in cui desideri automatizzare la creazione di tag script JSON-LD su una pagina. Una situazione potrebbe essere quella di invocare tale funzione negli eventi di modifica della navigazione del percorso. Quindi ho deciso di aggiungere una versione che funziona in un contesto di 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); } } 

    Non esiste un modo Angolare2 per aggiungere un tag script a un modello.

    L’uso di require(...) per caricare script esterni dalla class dei componenti è stato menzionato come soluzione temporanea (non l’ho provato io stesso)

    Utilizzare per aggiungere dynamicmente un tag di 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); } 

    Vedi anche angular2: compresi gli script js di terze parti nel componente

    In realtà non esiste un modo Angolare2 per aggiungere un tag script a un modello. ma puoi fare qualche trucco prima di tutto importerai AfterViewInit e ElementRef da angular2 in questo modo:

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

    allora li implementerai nella tua class in questo modo:

     export class example1 implements AfterViewInit{} 

    ed ecco un semplicissimo javascript dom trick che farai

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

    Quanto segue funziona con Angular 5.2.7:

    Le importazioni richieste sono:

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

    Implementare AfterViewInit:

     export class HeroesComponent implements AfterViewInit { 

    Se il tuo componente sta implementando più interfacce, separale con una virgola; per esempio:

     export class HeroesComponent implements OnInit, AfterViewInit { 

    Passa gli argomenti seguenti al costruttore:

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

    Aggiungi il metodo di visualizzazione del ciclo di visualizzazione di 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); } 

    Aggiungi la funzione membro afterScriptAdded.

    Questa funzione verrà chiamata dopo che lo script esterno è stato caricato correttamente. Quindi le proprietà o le funzioni che si desidera utilizzare da js esterni saranno accessibili nel corpo di questa funzione.

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