web-dev-qa-db-ja.com

Angularコンポーネントテンプレートにスクリプトタグを追加する

Angular2は、テンプレートから<script>タグを自動的に削除して、この機能を "poor's man" loader として使用しているユーザーを停止します。

ここでの問題は、スクリプトタグには現在、コードや他のスクリプトファイルを読み込むだけでなく、より多くの用途があるということです。 <script>タグに関するさらなる機能が将来導入される可能性もあります。

現在使用されているのは、次の形式のJSON-LDです

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

一般的に推奨される回避策は、 動的にスクリプトタグを追加ngAfterViewInitフックを介してドキュメントに追加することですが、これは明らかに適切なng2プラクティスではなく、サーバー側では動作しません。できる必要があります。

Angular2テンプレートに<script>タグを含めるために使用できる他の回避策はありますか(タグがブラウザ内で不活性である場合でも)、またはフレームワークが過度に考えられている場合ですか?この状況をangular2で解決できない場合、他にどのようなソリューションが存在する可能性がありますか?

35
Ian Belcher

ここでのパーティーに少し遅れるかもしれませんが、上記の回答はAngular SSR(たとえばdocument is not definedサーバー側またはdocument.createElement is not a function)ではうまく機能しないため、 Angular 4+で動作するバージョン、サーバーとブラウザーの両方のコンテキストで

コンポーネントの実装

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

サービスの実装

注:サービスはRenderer2を直接使用できません。実際、要素のレンダリングコンポーネントによって実行されることになっています。ただし、ページ上のJSON-LD scriptタグの作成を自動化する状況に陥ることがあります。例として、状況は、ルートナビゲーション変更イベントでそのような機能を呼び出すことです。したがって、Serviceコンテキストで機能するバージョンを追加することにしました。

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

スクリプトタグをテンプレートに追加するAngular2の方法はありません。

回避策としてrequire(...)を使用してコンポーネントクラスから外部スクリプトをロードすることが言及されました(自分で試したことはありません)

スクリプトタグを動的に追加するには

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スクリプトをコンポーネントに含める も参照してください

16

以下はAngular 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);
    }
  }
11
Ketan Yekale

実際ありませんAngular2テンプレートにscript tagを追加する方法。しかし、あなたはいくつかを行うことができますトリックまず第一にこのようにangle2からAfterViewInitElementRefをインポートします:

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

thenあなたはそのようにあなたのクラスにそれらを実装します:

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