Adding script tags in Angular component template
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);
}
}
Cannot Load .js File in Angular Module
Your script snippet does not "depend" on your component in your example snippet. You are requesting any input with type "range" in the whole web page (document's root) and that is not necessarily your component. (If you have 10 input[type="range"]
in your page, the script will have to handle that somehow, or it will only get the first one).
The way to do what you are trying to do IS to put it in the assets folder. If that is forbidden by any project rule, you have two options:
Upload your sidebar.js file into a different server or a different path and host it from there. Since it seems you don't have control over the files in your customer server, you can't make the assumption that the
/src/app/
directory is present (since it is not necessary to run the app after it has been built)Transform your .js file into a typescript file (.ts) and import it so that typescript can compile it.
To transform it into a .js file, just rename the file to sidebar.ts
and, at the file you want to include it, import for side effects only
What I recommend is that you wrap your file in a callable function that receives your component reference as a parameter so that you can specify which element is to related to as opposed to let it find in the document root but I suspect that would involve messing with the internals of the sidebar.js file. However if the sidebar file is a library or a module, this might be too time-consuming.
Angular 2 execute script after template render
ngAfterViewInit()
of AppComponent
is a lifecycle callback Angular calls after the root component and its children have been rendered and it should fit for your purpose.
See also https://angular.io/guide/lifecycle-hooks
Related Topics
Property 'Value' Does Not Exist on Type Eventtarget in Typescript
Passing in Dynamic Key:Value Pairs to an Object Literal
Unique Object Identifier in JavaScript
Replace All Occurrences in a String
Input File to Array JavaScript/Jquery
This.Setstate Isn't Merging States as I Would Expect
Why Does a Module Level Return Statement Work in Node.Js
Query Firestore Database for Document Id
Chrome Extension: Get Page Variables in Content Script
Reactjs Syntheticevent Stoppropagation() Only Works with React Events
How to Trigger a Bootstrap Modal Programmatically
JavaScript Reload the Page with Hash Value
Convert Nan to 0 in JavaScript
Batchsize Field Name Ignored in Field Projection