Ajout de balises de script dans le modèle de Composant angulaire

Angular2 supprime automatiquement les étiquettes <script> des modèles pour empêcher les gens d'utiliser cette fonctionnalité comme un " poor's man "loader .

le problème ici est que les balises de script ont actuellement plus d'utilisations que le simple chargement de code ou d'autres fichiers de script. Il est possible que d'autres fonctionnalités autour des étiquettes <script> soient également introduites à l'avenir.

une utilisation courante est JSON-LD qui prend le format

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

une solution de rechange couramment suggérée consiste à ajouter dynamiquement les balises de script au document via le crochet ngAfterViewInit , mais ce n'est évidemment pas la pratique ng2 appropriée et ne fonctionnera pas du côté du serveur, ce que JSON-LD doit évidemment être capable de faire.

y at-il d'autres solutions que nous pouvons utiliser pour inclure <script> balises dans angular2 modèles (même si l'étiquette est inerte dans le navigateur) ou est-ce un cas de le cadre étant trop opiniâtre? Quelles autres solutions pourraient exister si cette situation ne peut être résolue à angular2?

25
demandé sur Ian Belcher 2016-06-29 04:49:49

4 réponses

peut-être un peu en retard à la partie ici, mais puisque les réponses ci-dessus ne fonctionnent pas bien avec SSR angulaire (par exemple document is not defined côté serveur ou document.createElement is not a function ), j'ai décidé d'écrire une version qui fonctionne pour L'angle 4+, à la fois dans le contexte du serveur et du navigateur :

Mise En Œuvre Des Composantes

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

"151980920 Service De" Mise En Œuvre

NOTE: les Services ne peuvent pas utiliser Renderer2 directement. En fait, l'élément de rendu est supposé être fait par un composant . Cependant, vous pourriez vous trouver dans une situation où vous voulez automatiser la création de balises JSON-LD script sur une page. Une situation pourrait être d'invoquer une telle fonction lors d'événements de changement de route. J'ai donc décidé d'ajouter une version qui fonctionne dans un Service contexte.

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);
    }
}
18
répondu Nicky 2017-04-22 13:13:10

il n'y a pas de façon Angular2 d'ajouter une étiquette de script à un modèle.

L'utilisation de require(...) pour charger des scripts externes de la classe components a été mentionnée comme solution de contournement (Je ne l'ai pas essayé moi-même)

ajouter dynamiquement une balise de script, utilisez

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

Voir aussi angular2: incluant les scripts JS tiers dans le composant

14
répondu Günter Zöchbauer 2017-05-23 11:55:03

en Fait Il n'y a pas de Angular2 façon d'ajouter une étiquette de script à un modèle. mais vous pouvez faire quelque tour tout d'abord vous importerez AfterViewInit et ElementRef d'angular2 comme ceci:

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

puis vous les mettrez en œuvre dans votre classe comme cela:

export class example1 implements AfterViewInit{}

et voici un truc javascript dom très simple que vous allez faire

 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
répondu Mohsen M. Galal 2017-02-25 13:39:56

les travaux suivants avec L'angle 5.2.7:

les importations requises sont:

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

Implémenter AfterViewInit:

export class HeroesComponent implements AfterViewInit {

si votre composant implémente plusieurs interfaces, séparez-les par virgule; Par exemple:

export class HeroesComponent implements OnInit, AfterViewInit {

passer les arguments ci-dessous au constructeur:

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

Ajouter ngAfterViewInit méthode de vue du cycle de vie:

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

ajouter la fonction membre posterscriptadded.

cette fonction sera appelée après que le script externe a été chargé avec succès. Ainsi, les propriétés ou les fonctions que vous voulez utiliser à partir de js externes seront accessibles dans le corps de cette fonction.

 afterScriptAdded() {
    const params= {
      width: '350px',
      height: '420px',
    };
    if (typeof (window['functionFromExternalScript']) === 'function') {
      window['functionFromExternalScript'](params);
    }
  }
5
répondu Ketan Yekale 2018-03-06 05:59:33