Angular:在iFrame中运行脚本

时间:2018-03-30 11:45:35

标签: javascript html angular iframe

我将HTML作为字符串作为API响应。 HTML包含很少的内部脚本标记,其中包含在$(window).load()下调用的函数。如何在我的角应用中加载此HTML。

我尝试将HTML字符串响应附加到iFrame主体。 HTML加载但脚本标记不会执行,因为当角度路径更改时不会触发window.load事件。

如何解决此问题。 这是我的代码:

component.ts

ngOnInit() {
   const html = "
       <html>
         <body>
             <h1>Hello world</h1>
             <script>
               $(window).on('load', function() {
                 console.log('I am in the function') 
               })
             </script>
         </body>
      </html>"
   this.iframeDoc = this.iframe.nativeElement.contentDocument
   this.iframeDoc.body.innerHTML = html;
}

component.html

<iframe #iframe></iframe>

我希望在附加iframe内容时记录“我在函数中”。

编辑:

我还尝试将HTML附加到div而不是iFrame。这是代码:

component.html

<div id="wrapper" appRunScripts></div>

component.ts

ngOnInit() {
   const html = "
       <html>
         <body>
             <h1>Hello world</h1>
             <script>
               $(window).on('load', function() {
                 console.log('I am in the function') 
               })
             </script>
         </body>
      </html>"
   const wrapper = document.getElementById('wrapper');
   wrapper.innerHTML = html;
}

还添加了一个在HTML中运行脚本的指令。这是drective 运行scripts.directive.ts

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

@Directive({
  selector: '[appRunScripts]' 
})
export class RunScriptsDirective implements OnInit {

  constructor(private elementRef: ElementRef) { }
  ngOnInit(): void {
      setTimeout(() => { // wait for DOM rendering
          this.reinsertScripts();
      });
  }
  reinsertScripts(): void {
      const scripts = <HTMLScriptElement[]>this.elementRef.nativeElement.getElementsByTagName('script');
      const scriptsInitialLength = scripts.length;
      for (let i = 0; i < scriptsInitialLength; i++) {
          const script = scripts[i];
          const scriptCopy = <HTMLScriptElement>document.createElement('script');
          scriptCopy.type = script.type ? script.type : 'text/javascript';
          if (script.innerHTML) {
              scriptCopy.innerHTML = script.innerHTML;
          } else if (script.src) {
              scriptCopy.src = script.src;
          }
          scriptCopy.async = false;
          script.parentNode.replaceChild(scriptCopy, script);
      }
  }

}

1 个答案:

答案 0 :(得分:1)

ngAfterViewInit() {
    let content = `<html>
         <body>
             <h1>Hello world</h1>
             <script>
               $(window).on('load', function() {
                 console.log('I am in the function') 
               })
             </script>
         </body>
      </html>`;
    let doc = this.iframeDoc.nativeElement.contentDocument || this.iframeDoc.nativeElement.contentWindow;
    doc.open();
    doc.write(content);
    doc.close();
  }

访问右侧lyfecycle挂钩中的iframe

ngAfterViewInit - 在组件的视图完全初始化后调用的生命周期钩子

如果要运行脚本。注入:

 constructor(private sanitizer: DomSanitizer) {
    this.script = this.sanitizer.bypassSecurityTrustHtml(this.script);
  }

ngAfterViewInit() {
 let scripts = this.div.nativeElement.getElementsByTagName('script');
  for (let script of scripts) {
    eval(script.text)
  }
}

<强>模板:

<div #content [innerHTML]="script"> </div>

CODE EXAMPLE