Fiona
Fiona

Reputation: 1221

Angular 2/4: Add compiled component to an iframe

I have a new Angular app (can use v 2.4.10 or 4.0.0-rc.5), which uses an iframe to embed some pre-existing content. Using a method called when the iframe loads -- (load)="processIframe(extFrame)" -- I'm able to set up listeners via the Angular Renderer, and to grab references to child DOM elements (this answer helped with that process).

It's easy enough to set the content of an element in the iframe by replacing its innerHtml. However, what I need to do is the replace this html with a compiled Angular component. This component grabs some data from an API via a service.

Is there a way to replace DOM element content in the iframe with the compiled component?

Upvotes: 4

Views: 12345

Answers (1)

yurzui
yurzui

Reputation: 214047

You can create ComponentRef instance and then insert its compRef.location.nativeElement in desired place.

I would do it as follows Plunker Example:

@Component({
  selector: 'my-app',
  template: `
    <button (click)="createComponent()">Create component</button>
    <iframe #iframe (load)="onLoad()"></iframe>
  `,
})
export class App implements AfterViewInit, OnDestroy {
  @ViewChild('iframe') iframe: ElementRef;

  doc: any;
  compRef: ComponentRef<DynamicComponent>;

  constructor(
    private vcRef: ViewContainerRef,
    private resolver: ComponentFactoryResolver) {}


  createComponent() {
    const compFactory = this.resolver.resolveComponentFactory(DynamicComponent);
    this.compRef = this.vcRef.createComponent(compFactory);

    this.doc.body.appendChild(this.compRef.location.nativeElement);
  }

  onLoad() {
    this.doc = this.iframe.nativeElement.contentDocument || 
               this.iframe.nativeElement.contentWindow;
  }

  ngAfterViewInit() {
    this.onLoad(); // in Firefox state is uninitialized while 
                   // in Chrome is complete so i use `load` event for Firefox
  }

  ngOnDestroy() {
    if(this.compRef) {
      this.compRef.destroy();
    }
  }
}

Don't forget to add DynamicComponent to `entryComponents array

Upvotes: 17

Related Questions