How to render a dynamic template with components in Angular2

18,013

Solution 1

Problem solved Thanks to Yurzui,

https://plnkr.co/edit/TAbupH4si62x10QZ7xuc?p=preview

The generic HTML outlete from a different post (Angular 2.1.0 create child component on the fly, dynamically) can be used to render templates with custom directives in them.

Don't forget to import a module with all the custom components that you want to render!

export function createComponentFactory(compiler: Compiler, metadata: Component): Promise<ComponentFactory<any>> {
const cmpClass = class DynamicComponent {};
const decoratedCmp = Component(metadata)(cmpClass);

// Import the module with required components here
@NgModule({ imports: [CommonModule, RouterModule, SharedModule], declarations: [decoratedCmp] })
class DynamicHtmlModule { }

return compiler.compileModuleAndAllComponentsAsync(DynamicHtmlModule)
   .then((moduleWithComponentFactory: ModuleWithComponentFactories<any>) => {
    return moduleWithComponentFactory.componentFactories.find(x => x.componentType === decoratedCmp);
  });
}

Solution 2

I made tiny changes for using my own components (such as HomeComponent) at @Yurzui and @Linksonder 's solutions. https://plnkr.co/edit/27x0eg?p=preview

It's basically adding AppModule to DynamicHtmlModule as additional import inside of createComponentFactory().

@NgModule({ imports: [AppModule, CommonModule, RouterModule, SharedModule], declarations: [decoratedCmp] })
class DynamicHtmlModule { }

And exports our own components at AppModule

@NgModule({
  ...
  exports: [HomeComponent, AboutComponent],
  ...
})
export class AppModule { }
Share:
18,013
Linksonder
Author by

Linksonder

Currently employed as software developer teacher at Avans but i r also a KICK ASJ computer wizzard :D (no not realy, but i know how to use google to debug my apps :P (o) It's something! )

Updated on June 05, 2022

Comments

  • Linksonder
    Linksonder almost 2 years

    I've tried many stackoverflow options like Load existing components dynamically Angular 2 Final Release.

    What i want to do is get a html page with a ajax request and render/compile this template in my custom component.

    I've figured out that angular2 has two deprecated components and that i have to use ComponentFactoryResolver.

    In my old solution i could just set a '[innerHtml]' to render the HTML. Now i need a new solution.

    Who can help me out?

    page.component.ts

    import { Component, ViewChild, ViewContainerRef, ComponentFactory, OnInit, ComponentFactoryResolver } from '@angular/core';
    import { ActivatedRoute, Params } from '@angular/router';
    
    
    @Component({
        selector: "wd-page",
        templateUrl: "/app/page/page.component.html",
        providers: []
    })
    export class PageComponent implements OnInit {
    
        // we need the viewcontainer ref, so explicitly define that, or we'll get back
        // an element ref.
        @ViewChild('dynamicChild', { read: ViewContainerRef })
        private target: ViewContainerRef;
    
        private page = {
            Source: "<div><h2>Hello world</h2><one-of-my-components></one-of-my-components></div>"
        }
    
    
        constructor(
            private vcRef: ViewContainerRef,
            private resolver: ComponentFactoryResolver) { }
    
    
            ngOnInit() {
                //What code do i need here?
            }
    }
    
    <div #dynamicChild></div>
    
    <!-- Old implementation!
    
        <div *ngIf="!showSource" [innerHTML]="page">
        </div>
    -->