Angular2 removes <script>
tags automatically from templates to stop people using this functionality as a "poor's man" loader.
The issue here is that script tags currently have more uses than just loading code or other script files. There is the possibility that further functionality around <script>
tags will be introduced in future as well.
One current use is JSON-LD which takes the format
<script type="application/ld+json"> { "@context":"http://schema.org", "@type":"HealthClub", ... } </script>
A commonly suggested work around is to dynamically add script tags to the document via the ngAfterViewInit
hook, but this is obviously not proper ng2 practice and will not work server side, which JSON-LD obviously needs to be able to do.
Are there any other workarounds that we can use to include <script>
tags in angular2 templates (even if the tag is inert within the browser) or is this a case of the framework being too opinionated? What other solutions might exist if this situation can't be solved in angular2?
Bookmark this question. Show activity on this post. I've already done a bit of reading and searching and pretty much everything I find points to that a script tag cannot be included in a template in Angular 2.
Angular recognizes the value as unsafe and automatically sanitizes it, which removes the script tag but keeps safe content such as the text content of the script tag. This way it eliminates the risk of script injection attacks.
In angular we can add those script in two ways first one is using the pure javascript way and other in angular way which also work on server application.
To include a JavaScript library in your TypeScript application you must first include it in your HTML file as a script tag. To use the library you must add the following to one of your ts files: declare var libraryVar: any; Replace libraryVar with a variable, function, or class within your JavaScript library.
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:
Component Implementation
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 Implementation
NOTE: Services cannot use Renderer2
directly. In fact, rendering an 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. As an example, 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.
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); } }
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With