Maybe a little late to the party here, but since the above answers do not work well with Angular SSR (e.g. document is not defined
server-side or document.createElement is not a function
), I decided to write a version that works for Angular 4+, in both server and browser context:json
Component Implementationpromise
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); } }
Service Implementationangular2
NOTE: Services cannot use Renderer2
directly. In fact, rendering element is supposed to be done by a Component. However, you might find yourself in situation where you want to automate the creation of JSON-LD script
tags on a page. A situation could be to invoke such function on route navigation change events. Hence I decided to add a version that works in a Service
context.app
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); } }
The following works with Angular 5.2.7:
The required imports are:
import { Inject, AfterViewInit, ElementRef } from '@angular/core'; import { DOCUMENT } from '@angular/common';
Implement AfterViewInit:
export class HeroesComponent implements AfterViewInit {
If your component is implementing more that one interfaces, separate them by comma; for example:dom
export class HeroesComponent implements OnInit, AfterViewInit {
Pass the below arguments to constructor:
constructor(@Inject(DOCUMENT) private document, private elementRef: ElementRef) { }
Add ngAfterViewInit method of view life-cycle:
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); }
Add afterScriptAdded member function.
This function will be called after the external script is loaded successfully. So the properties or functions you want to use from external js will be accessed in the body of this function.
afterScriptAdded() { const params= { width: '350px', height: '420px', }; if (typeof (window['functionFromExternalScript']) === 'function') { window['functionFromExternalScript'](params); } }
Actually There is no Angular2 way of adding a script tag to a template. but you can do some trickfirst of all you will import AfterViewInit
and ElementRef
from angular2 like this :
import {Component,AfterViewInit,ElementRef} from 'Angular2/core';
then you will you will implement them in your class like that :
export class example1 implements AfterViewInit{}
and here is a very simple javascript dom trick you gonna do
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 } }