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.
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();
}
}
use this:
let iframe = document.getElementById('iframe') as HTMLIFrameElement
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.
I solved the problem in the following way:
const element: HTMLIFrameElement = document.getElementById('iframe') as HTMLIFrameElement;
const iframe = element.contentWindow;
if (iframe !== null) {
...
}