1

Im trying to create a plugin that takes a component as argument and render its content in the end of body tag. Just like the plugins that work with jQuery.

@Component({
    selector: 'some-selector',
    template: 'This is FirstComponent'
})
class FirstComponent{}

@Component({
    selector: 'app',
    template: 'The root component'
})
class AppComponent{
    // ImaginaryModalOpener is what i want to achieve.
    // a standalone function that can take a component and render it in dom    
    // at the bottom of the body tag
    ImaginaryModalOpener(FirstComponent);
}

I have seen a lot of stackoverflow questions about rendering a dynamic components but they use directives or HTML markup in the root Component to start with. In my case the Root template will have no directives or components for ImaginaryModalOpener.

Please point out if i've missed something.

Boniface Pereira
  • 188
  • 2
  • 11
  • [this answer](https://stackoverflow.com/a/44853707/2545680) should give you the solution, it doesn't user view container ref but instead uses direct DOM node to insert a component into – Max Koretskyi Jul 10 '17 at 04:42

2 Answers2

1

Get ViewContainerRef from AppComponent how to get root viewContainerRef of angular2 aplication

and add a component to this ViewContainerRef like for example shown in Angular 2 dynamic tabs with user-click chosen components

The added component will be added as sibling to AppComponent. If AppComponent is a child of <body>, the dynamically added component will also be a child of <body>.

Günter Zöchbauer
  • 623,577
  • 216
  • 2,003
  • 1,567
  • 1
    Thanks!, i finally came up with this code, appends the component to the body. Cheers. let factory = this.resolver.resolveComponentFactory(options.component); let newNode = document.createElement('div'); document.body.appendChild(newNode); const ref: any = factory.create(this.injector, [], newNode); this.app.attachView(ref.hostView); – Boniface Pereira Jul 21 '17 at 19:06
1

You can create a Renderer2 on demand from a RendererFactory2 and use this to add to document.body.

I needed to add an iframe for a third party tracking API that needed me to put an iframe on the page when the user made a purchase. So this example logically belongs in a service and not a component - it just so happens that the implementation results in a DOM element being added.

Inject these (even if providerIn: 'root') :

 private rendererFactory: RendererFactory2,
 @Inject(DOCUMENT) private document: Document

Then to create an iFrame:

createIFrame(url: string)
{
    const iframe: HTMLIFrameElement = document.createElement('iframe');
    iframe.src = url;
    iframe.width = '100';
    iframe.height = '100';
    iframe.frameBorder = '1';

    const renderer = this.rendererFactory.createRenderer(null, null);
    renderer.appendChild(this.document.body, iframe);
}

That's it. No messing around with AppComponent or ViewReference etc. - this is basically just pure Javascript in Angular form.

Simon_Weaver
  • 140,023
  • 84
  • 646
  • 689