2017-01-09 37 views
2

我已經通過http.get()方法加載HTML頁面,並且我將此頁面的內容添加到div標記。Angular 2如何從innerHTML執行腳本標記

getRequestToAssignPage (param: string) : any { 

    return this.$http.get(param) 
     .map((res: Response) => { 

      this.status = res; 

      return res.text(); 
     }) 
     .toPromise() 
     .then(response => { 



      let restr: string = response; 



      restr = restr.replace(/(<head[^>]*)(?:[^])*?\/head>/ig, '') 
       .replace(/(<(\/?)body([^>]*?)>)/g, '') 
       .replace(/(<style[^>]*)(?:[^])*?\/style>/g, '') 
       .replace(/(<(\/?)html([^>]*?)>)/g, '') 
       .replace(/(<app-root[^>]*)(?:[^])*?\/app-root>/ig, '') 
       .replace(/(<\?[\s\S]*?\?>)|(<!DOCTYPE\s+\w+\s+\[[\s\S]*?\]>)|(<!\w[\s\S]*?>)/g, '') 
       .replace(/(href\s*=\s*(?:"))/ig, 'href="/#') 
       .replace(/(href\s*=\s*(?:'))/ig, "href='/#"); 



      this.response = restr; 


     }) 
     .catch(error => this.status = error); 

} 

你怎麼樣,你看,這個方法,把變量響應,並解析正則表達式 好的字符串,接下來我將它添加到div的,這樣

<div [innerHTML]="response | safe"></div> 

好,我顯示頁面。但是,腳本不起作用。它們存在於div標籤中,但不會執行。

我曾試圖做到這一點與eval()但這種不良完

let scripts: string[] = restr.match(/\<scr[\s\S]*?ipt>/g); 

      this.srcfield.nativeElement.innerHTML = ''; 

      scripts.forEach((value, index) => { 
       eval.call(null, (this.srcfield.nativeElement.innerHTML = value)); 
      }); 

SyntaxError: Unexpected token <

爲什麼innerHTML不執行加載腳本標籤?我該如何解決這個問題?

回答

2

在模板中,您可以設置類似:

<div #htmlContainer [innerHTML]="trustedHTML"></div> 

在相應的組件,您可以將HTML加載到您的模板,建立script標籤的數組,每個eval之一:

@ViewChild('htmlContainer') container; 

ngOnInit() { 
    this.http.get('html-file.html').subscribe((res: Response) => { 
    this.trustedHTML = this.sanitizer.bypassSecurityTrustHtml(res.text()); 

    setTimeout(() => { //wait for DOM rendering 
     let scripts = this.container.nativeElement.getElementsByTagName('script'); 
     for (let script of scripts){ 
     eval(script.text) 
     } 
    }) 

    }); 

我恨,我不得不求助於使用setTimeouteval的東西,所以看似簡單,但很有效。

...但不適用於<script src="...。我結束了導入jQuery並使用$(parent).load(url);。如果有人有一個純粹的Angular解決方案,請張貼它。

1

基於Adam的解決方案,您可以與管道一起實施自定義指令並將腳本重新插入到DOM中。這將解釋兩種情況:內聯腳本和「src」腳本。請記住,允許這樣的腳本非常危險。

管:

import { Pipe, PipeTransform } from '@angular/core'; 
import { DomSanitizer } from '@angular/platform-browser'; 

@Pipe({ name: 'safeHtml' }) 
export class SafeHtmlPipe implements PipeTransform { 
    constructor(private sanitizer: DomSanitizer) { } 

    transform(html) { 
     return this.sanitizer.bypassSecurityTrustHtml(html); 
    } 
} 

指令:

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

@Directive({ selector: '[runScripts]' }) 
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); 
     } 
    } 
} 

用法:

<div [innerHTML]="myDynamicMarkup | safeHtml" runScripts></div>