Angular 2 how to execute script tag from innerHTML

后端 未结 2 1175
悲哀的现实
悲哀的现实 2020-12-15 00:04

I have load the HTML page by http.get() method, and i add content this page to div tag.

getRequestToAssignPage (param: string) : an         


        
相关标签:
2条回答
  • 2020-12-15 00:38

    In your template, you can set up something like:

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

    In the corresponding component, you can load your HTML into your template, build up an array of script tags, and eval each one:

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

    I hate that I have to resort to using setTimeout and eval for something so seemingly simple, but it works.

    ...but not for <script src=".... I ended up importing jQuery and using $(parent).load(url);. If someone has a pure Angular solution, please post it.

    0 讨论(0)
  • 2020-12-15 00:48

    Based on the Adam's solution you can implement a custom directive along with the pipe and re-insert scripts into the DOM. This would account for both cases: inline scripts and "src" scripts. Keep in mind that allowing scripts like so is very dangerous.

    Pipe:

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

    Directive:

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

    Usage:

    <div [innerHTML]="myDynamicMarkup | safeHtml" runScripts></div>
    
    0 讨论(0)
提交回复
热议问题