Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Angular 2/4: Add compiled component to an iframe

Tags:

angular

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?

like image 277
Fiona Avatar asked Dec 03 '22 22:12

Fiona


1 Answers

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

like image 151
yurzui Avatar answered Jan 22 '23 13:01

yurzui