Adding a script tag in Angular inside a specific component

In one of my latest projects I stumbled upon the need to run an external script, or basically have a <script> tag, in one specific component, more specifically a routed component or a page if you will.

The scenario I’m talking about was due to the requirement of informing Google Ads Conversion Tracking (GACT) in a registration form written in Angular.

For obvious reasons, I did not want to load GACT script on all of my Angular application pages, therefor I did not want to put it in my index.html file, but when that’s the case, for security reasons, Angular will not let you just add a <script> tag in your template.

We had to think of a solution…

After some thinking and research we found the following solution to the problem: have a special component, let’s call it the cool name “ScriptHackComponent” which will load a script tag to the head of the page whenever we use the tag <app-script-hack>, which basically mimics a standard HTML <script> tag. And yes, Stackoverflow helped with the solution, but we perfected it a little bit more.

The component we’ve added ended up looking like this:

<div #script="" style.display="none">
    <ng-content></ng-content>
</div>
import { isPlatformBrowser } from '@angular/common';
import { AfterViewInit, Component, ElementRef, Inject, Input, PLATFORM_ID, ViewChild } from '@angular/core';

@Component({
    selector: 'app-script-hack',
    templateUrl: './scripthack.component.html'
})
export class ScriptHackComponent implements AfterViewInit {
    @Input()
    src: string;

    @Input()
    type: string;

    @ViewChild('script') script: ElementRef;

    constructor(@Inject(PLATFORM_ID) private platformId: Object) {
    }

    convertToScript() {
        const element = this.script.nativeElement;
        const parent = element.parentElement;
        const script = document.createElement('script');
        script.type = this.type ? this.type : 'text/javascript';
        if (this.src) {
            script.src = this.src;
        }

        if (element.innerHTML) {
            script.innerHTML = element.innerHTML;
        }

        parent.parentElement.replaceChild(script, parent);
    }

    ngAfterViewInit() {
        if (isPlatformBrowser(this.platformId)) {
            this.convertToScript();
        }
    }
}

After creating this component we could have used it just like a standard <script> tag, but with the name change <app-script-hack>, like this.

<app-script-hack type="text/javascript" src="path_to_external_script.js">
</app-script-hack>

Just a very important note, make sure you never let any unsafe code be compiled by the Angular engine with this tag, that might let your users create unsafe “reflection” code which can hurt other users by running harmless JavaScript scripts from and external source.

I hope that was helpful for you.

Happy coding!

Comments

Leave a Reply

Your email address will not be published. Required fields are marked *