iframe inside angular2 component, Property 'co

2019-02-12 15:55发布

问题:

I have an iframe inside a angular2 component, and I am trying to change the content of the iframe by accessing the contentWindow.
The iframe should contain a simple button.

My code:

    import { Component } from '@angular/core';
    @Component({
      moduleId: module.id,
      selector: 'component-iframe',
      template: '<iframe id="iframe"></iframe>'
    })
    export class ComponentIframe  {
      constructor() {
        let iframe = document.getElementById('iframe'); 
        let content = '<button id="button" class="button" >My button </button>';
        let doc =  iframe.contentDocument || iframe.contentWindow;
        doc.open();
        doc.write(content);
      doc.close();
    }
   }

If I comment the constructor's code and start the app, it compiles and runs correctly. Then I uncomment and all runs perfectly (the button is present in the iframe).

If I decomment the code then start the app (npm start) I have compilation bugs with the message:

Property 'contentWindow' does not exist on type 'HTMLElement'

.

I also tried the alternative of putting the costructor's code into ngOnInit(), ngAfterContentInit(), ngAfterViewInit() but the error persists.

回答1:

The template doesn't exist in the DOM yet when the constructor is executed

Use instead

import { Component, ViewChild, ElementRef } from '@angular/core';
@Component({
  moduleId: module.id,
  selector: 'component-iframe',
  template: '<iframe #iframe></iframe>'
})
export class ComponentIframe  {
  @ViewChild('iframe') iframe: ElementRef;

  ngAfterViewInit() {
    let content = '<button id="button" class="button" >My button </button>';
    let doc =  this.iframe.nativeElement.contentDocument || this.iframe.nativeElement.contentWindow;
    doc.open();
    doc.write(content);
    doc.close();
  }
}


回答2:

use this:

let iframe = document.getElementById('iframe') as HTMLIFrameElement


回答3:

If the content of the IFRAME is created by the same origin then I would suggest to use the IFRAME attribute srcDoc to set and change content in IFRAME.

@Component({
  selector: 'my-app',
  template: `
    <p><label for="text">Write content here...</label></p>
    <textarea 
        #text
        rows="10" 
        cols="47" 
        placeholder="Write some HTML content here..." 
        [(ngModel)]="srcDocContent"></textarea>

    <p>Preview HTML content in IFRAME</p>
    <iframe 
        sandbox="allow-same-origin" 
        [attr.srcDoc]="srcDocContent"></iframe>
  `
})
export class App {

  srcDocContent:string

  constructor() {
    this.srcDocContent='Some <strong>HTML</strong> content here...'
  }
}

See this PLUNKER DEMO

This will let the native HTML elements untouched to remain compatible with Angular Universal.



回答4:

I solved the problem in the following way:

const element: HTMLIFrameElement = document.getElementById('iframe') as HTMLIFrameElement;
const iframe = element.contentWindow;
if (iframe !== null) {
  ...
}