10

Is there a way to include third party JS scripts inside an Angular2 component instead of including it in index.html?

I have a table component that wraps dataTables. It's the only component that needs the dataTables js/css includes. It would be nice if I could keep my index.html cleaner. The component decorator does let you specify css files.

I tried moving my script tags inside my component html, but that doesn't seem to work.

dvulanov
  • 145
  • 1
  • 1
  • 10

1 Answers1

12

Script tags in component templates are removed. A workaround is to create the script tag dynamically in ngAfterViewInit()

See also https://github.com/angular/angular/issues/4903

import { DOCUMENT } from '@angular/common';
...

constructor(private @Inject(DOCUMENT) document, 
            private elementRef:ElementRef) {};

ngAfterViewInit() {
  var s = this.document.createElement("script");
  s.type = "text/javascript";
  s.src = "http://somedomain.com/somescript";
  this.elementRef.nativeElement.appendChild(s);
}

See also https://stackoverflow.com/a/9413803/217408

Günter Zöchbauer
  • 623,577
  • 216
  • 2,003
  • 1,567
  • this does't seems to work properly angular throws error `this.elementRef.nativeElement.append is not a function` ? why ? – Pardeep Jain Feb 24 '16 at 06:23
  • @PardeepJain I guess the correct function name is `appendChild(s)` in JS/TS. In Dart it's `append(s)` and I mixed it up. – Günter Zöchbauer Feb 24 '16 at 13:25
  • I got a ref via: document.getElementById instead. The scripts load, but the js code that needs these scripts doesn't execute properly on initial load (after refresh it works). Really, I don't think this would be a solution even if it worked. My questions was to see if there is a clean/standard "angular way" to include js dependencies only in the components that need them. – dvulanov Feb 24 '16 at 13:40
  • No, currently there are only workarounds. – Günter Zöchbauer Feb 24 '16 at 13:59
  • I get document is undefined – Nitin Rastogi Jul 21 '17 at 14:30
  • I updated my answer, but I haven't tried it this way myself yet. Adding `declare var document;` below the imports should work as well. – Günter Zöchbauer Jul 21 '17 at 14:39
  • I am using this solution and it works fin for me, but is it really safe to add a script like this directly to the DOM? – C00kieMonsta Oct 30 '18 at 10:21
  • @C00kieMonsta not sure what you mean. What would be the alternative? What part do you think is a security concern (in addition to what adding any script by any way would be)? – Günter Zöchbauer Oct 30 '18 at 10:55
  • My concern is cross-site scripting. It is possible that the client does that when adding a script element on the fly? – C00kieMonsta Oct 30 '18 at 10:57
  • 1
    If you make the script source dependent on user input, then you of course open a barn door for XSS attacks. If the string is hardcoded in the applications source code, I don't see a problem. – Günter Zöchbauer Oct 30 '18 at 11:00
  • Can’t the attacker replace the hard coded string inside the Dom or angular prevents such behaviour? – C00kieMonsta Oct 30 '18 at 11:06
  • Not sure what you mean with "the attacker". If "the attacker" somehow is able to get that kind of access there is hardly anything he can't do. I don't see a difference in modifying a script tag in HTML or in JavaScript. Angular isn't really involved here. Above code is basically procedural TypeScript that is transpiled to JavaScript. The only involvement from Angular is that it invokes the code by calling the components lifecycle method `ngAfterViewInit` that contains the code we are discussing. – Günter Zöchbauer Oct 30 '18 at 11:10