Need to insert Script tag in angular 2

前端 未结 5 1086
被撕碎了的回忆
被撕碎了的回忆 2020-11-27 18:22

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.

相关标签:
5条回答
  • 2020-11-27 18:23

    As per Angular documentation, the <script> element is forbidden and cannot be used in templates. <script> is ignored when used in templates.

    Check here. Angular security

    0 讨论(0)
  • 2020-11-27 18:24

    Having scripts in your views is usually a bad practice. If you insist on doing this you can use this component:

    scripthack.component.html:

    <div #script style.display="none">
      <ng-content></ng-content>
    </div>
    

    scripthack.component.ts:

    import { Component, ElementRef, ViewChild, Input } from '@angular/core';
    
    @Component({
        selector: 'script-hack',
        templateUrl: './scripthack.component.html'
    })
    export class ScriptHackComponent {
    
        @Input()
        src: string;
    
        @Input()
        type: string;
    
        @ViewChild('script') script: ElementRef;
    
        convertToScript() {
            var element = this.script.nativeElement;
            var 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;
            }
            var parent = element.parentElement;
            parent.parentElement.replaceChild(script, parent);
        }
    
        ngAfterViewInit() {
            this.convertToScript();
        }
    }
    

    usage (inline):

    <script-hack>alert('hoi');</script-hack>
    

    usage (external):

    <script-hack src="//platform.twitter.com/widgets.js" type="text/javascript"></script-hack>
    
    0 讨论(0)
  • 2020-11-27 18:27

    Turns out I was thinking about this a bit wrong. I was trying to find a way to put the script into the template by using standard Angular template variables. When Angular populates the template, it cleanses the values and so the script tags are lost.

    I managed to finally get the script tags in following this article: https://netbasal.com/angular-2-security-the-domsanitizer-service-2202c83bd90#.7njysc6z1

    That then left me with the problem described by: Angular2 dynamically insert script tag

    I then moved the logic into the component class based on this: Where does DOM manipulation belong in Angular 2?

    0 讨论(0)
  • 2020-11-27 18:41

    Include jQuery in the JavaScript Console

    Use the following above to solve your problem. It includes JQuery by inserting script tags into the DOM but it can work for any tag or javascript library that you desire. You can use the innerHTML attribute to customize the contents of the tag if you wish.

    0 讨论(0)
  • 2020-11-27 18:45

    I had a similar use case, where I don't know if the HTML will contain a script tag. Since HTML5 doesn't execute the script if it's part of an innerHTML assignment, I used a slightly different approach.
    This is part of a plugin system, so I needed to be able to add html+scripts on demand.

    Source here - https://github.com/savantly-net/sprout-platform/blob/development/web/sprout-web-ui/src/app/dynamic/dynamic.component.ts

    import { Component, Input, AfterViewInit, ViewChild, Directive, ElementRef } from '@angular/core';
    
    @Directive({
      /* tslint:disable-next-line:directive-selector */
      selector: 'dynamic-directive'
    })
    export class DynamicDirective {}
    
    @Component({
      template: `<dynamic-directive></dynamic-directive>`
    })
    export class DynamicComponent implements AfterViewInit {
      @Input() body: any;
      @ViewChild(DynamicDirective, {read: ElementRef}) dynamic: ElementRef;
    
      constructor() { }
    
      // loads all the html from the plugin, but removes the script tags and appends them individually,
      // since html will not execute them if they are part of the innerHTML
      ngAfterViewInit(): void {
        const div = document.createElement('div');
        div.innerHTML = this.body;
        const scriptElements = [];
        const scriptNodes = div.querySelectorAll('script');
        for (let i = 0; i < scriptNodes.length; i++) {
          const scriptNode = scriptNodes[i];
          // Create a new script element so HTML5 will execute it upon adding to DOM
          const scriptElement = document.createElement('script');
          // Copy all the attributes from the original script element
          for (let aI = 0; aI < scriptNode.attributes.length; aI++) {
            scriptElement.attributes.setNamedItem(<Attr>scriptNode.attributes[aI].cloneNode());
          }
          // Add any content the original script element has
          const scriptContent = document.createTextNode(scriptNode.textContent);
          scriptElement.appendChild(scriptContent);
          // Remove the original script element
          scriptNode.remove();
          // add the new element to the list
          scriptElements.push(scriptElement);
        }
        this.dynamic.nativeElement.appendChild(div);
        // Finally add the new script elements to the DOM
        for (let i = 0; i < scriptElements.length; i++) {
          this.dynamic.nativeElement.appendChild(scriptElements[i]);
        }
      }
    }
    
    0 讨论(0)
提交回复
热议问题