1

I get HTML as string as API response. The HTML contains few internal script tags which has functions called under $(window).load(). How do I load this HTML in my angular app.

I tried appending HTML string response to iFrame body. The HTML loads but the script tags aren't executed as window.load event is not fired when the angular route changes.

How do I approach this problem. Here's my code:

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>

I want "I am in the function" to be logged when the iframe content is appended.

EDIT:

I also tried appending the HTML to a div instead of an iFrame. Here's the code:

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

Also added a directive to run scripts within HTML. Here's the drective run-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);
      }
  }

}
2
  • Make sure you include JQuery since you using $(window). Commented Mar 30, 2018 at 11:54
  • @sajankumarvijayan Yes I have done that. The code runs without error. But just that script isn't executed. Commented Mar 30, 2018 at 11:56

1 Answer 1

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

Access to your iframe in right lyfecycle hook.

ngAfterViewInit - Lifecycle hook that is called after a component's view has been fully initialized

If you want to run script. Inject:

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

template:

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

CODE EXAMPLE

Sign up to request clarification or add additional context in comments.

2 Comments

How I achieve the same use case using div and not iframe? Check EDIT
@chiragshah, updated answer, but I can't access for jQuery for now.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.