需要在角度2中插入脚本标记

时间:2017-02-25 16:07:28

标签: angular

我已经完成了一些阅读和搜索,而且几乎我发现的一切都指出脚本标签不能包含在Angular 2的模板中。

  

我们会像您一样故意从模板中删除标签   不应该使用它们按需加载代码。   https://github.com/angular/angular/issues/4903 [2015]

然而 - 有一个函数bypassSecurityTrustScript

我想知道Angular 2中的bypassSecurityTrustScript何时以及如何使用?

我知道有类似的问题被问到: Angular2 dynamically insert script tag - 虽然没有人回答他们如何使用bypassSecurityTrustScript的问题,但我不确定提供的问题答案是如何工作的,因为它似乎在模板中使用JavaScript。

5 个答案:

答案 0 :(得分:19)

在您的视图中使用脚本通常是一种不好的做法。如果你坚持这样做,你可以使用这个组件:

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();
    }
}

用法(内联):

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

用法(外部):

<script-hack src="//platform.twitter.com/widgets.js" type="text/javascript"></script-hack>

答案 1 :(得分:7)

原来我觉得这有点不对劲。我试图通过使用标准的Angular模板变量找到一种将脚本放入模板的方法。当Angular填充模板时,它会清除值,因此脚本标记会丢失。

我设法在以下文章中获得了脚本标记: https://netbasal.com/angular-2-security-the-domsanitizer-service-2202c83bd90#.7njysc6z1

然后让我遇到了问题:Angular2 dynamically insert script tag

然后我基于此将逻辑移动到组件类中: Where does DOM manipulation belong in Angular 2?

答案 2 :(得分:0)

我有一个类似的用例,我不知道HTML是否包含脚本标记。由于HTML5不是执行脚本(如果它是innerHTML分配的一部分),我使用的方法略有不同。
这是插件系统的一部分,所以我需要能够按需添加html +脚本。

来源 - 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]);
    }
  }
}

答案 3 :(得分:0)

根据Angular文档,