3

I have a script that I would like to run on one component only. I have managed to achieve adding the script on the component but a couple of things happen that I'm not entirely sure how to resolve.

  1. If I navigate to the component, the script is added to the DOM, but it isn't firing. If I refresh the page, it works
  2. If I navigate away to another component and return, the script is added again, and it can keep building up

component.ts

import { Component, OnInit } from '@angular/core';
import { Renderer2, Inject } from '@angular/core';
import { DOCUMENT } from '@angular/platform-browser';

@Component({
  selector: 'app-privacy',
  templateUrl: './privacy.component.html',
  styles: []
})
export class PrivacyComponent implements OnInit {

  constructor(private _renderer2: Renderer2, @Inject(DOCUMENT) private _document) {
    let s = this._renderer2.createElement('script');
    s.type = `text/javascript`;
    s.src = `../../assets/scripts/privacy.js`;

    this._renderer2.appendChild(this._document.body, s);
   }

  ngOnInit() {
  }

}
5
  • You should add a onload callback to your script element, so you know when it is done loading. As for removing the script, I think it is best if you remove it from the dom in the ngOnDestroy lifecycle hook of your component. Commented Mar 20, 2019 at 14:55
  • Great, thank you. In regards to point #2, do you have an example of how you would remove added scripts in ngDestroy? Commented Mar 20, 2019 at 15:03
  • you can save the returned Node from appendChild in your component and simply .remove() in Destroy lifecycle hook. ill create an example for you. Commented Mar 20, 2019 at 15:11
  • Oh, i see you are using Renderer2, i dont have much experience with it but you can try in Destroy hook: this._renderer2.removeChild(this._document.body, s) Commented Mar 20, 2019 at 15:19
  • 1
    Sorted, thanks. If you write that up as an answer, I'll mark it :) Commented Mar 20, 2019 at 15:24

2 Answers 2

1

You need to add the onload (if you need to support IE make sure to also support onreadystatechange) handler to your script element which can call a function you want to execute when the script is finished loading.

To remove the script onNgDestroy, save a reference of createElement? on the Component and remove this in Destroy lifecycle hook.

import { Component, OnInit, OnDestroy } from '@angular/core';
import { Renderer2, Inject } from '@angular/core';
import { DOCUMENT } from '@angular/platform-browser';

@Component({
  selector: 'app-privacy',
  templateUrl: './privacy.component.html',
  styles: []
})
export class PrivacyComponent implements OnInit, OnDestroy {
  private s: any;
  constructor(private _renderer2: Renderer2, @Inject(DOCUMENT) private _document) {
    this.s = this._renderer2.createElement('script');
    this.s.type = `text/javascript`;
    this.s.src = `../../assets/scripts/privacy.js`;
    this.s.onload = this.doneLoading;

    this._renderer2.appendChild(this._document.body, this.s);
  }

  doneLoading () {
    // do what you need to do
  }


  ngOnDestroy() {
    // this removes the script so it won't be added again when the component gets initialized again.
    this._renderer2.removeChild(this._document.body, this.s)
  }

  ngOnInit() {
  }

}
Sign up to request clarification or add additional context in comments.

Comments

0

Your approach in running this js file is wrong, you should do following to achieve this in the clean way:

  1. Add your js file to the assets (for example assets/js/privacy.js)
  2. Add file to the .angular-cli.json scripts
  3. Now you can call your js functions from angular components if you declare them in the component

angular-cli.json

"scripts": [
  "assets/js/privacy.js"
]

component.ts

import { Component, OnInit } from '@angular/core';

declare function myFunc(): any; // function from privacy.js 

@Component({
  selector: 'app-privacy',
  templateUrl: './privacy.component.html',
  styles: []
})
export class PrivacyComponent implements OnInit {

  constructor() {
   }

  ngOnInit() {
      myFunc(); // call it
  }

}

4 Comments

this only works if the script is loaded globally (ie added to the scripts array in angular.json)
@thinkwinwin he has it added globally, see s.src = ../../assets/scripts/privacy.js; true adding file to .angular-cli.json missing
I haven't added it globally. That's just where it's stored in my directory. If that helps.
why cant you add this globally instead of doing such hacks? :)

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.