Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to render a dynamic template with components in Angular2

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>
-->
like image 745
Linksonder Avatar asked Oct 17 '16 17:10

Linksonder


People also ask

Can we create component dynamically in Angular?

If we go by the Angular definition, a factory component Angular is a base class for a factory that can create a component dynamically. Instantiate a factory for a given type of component with resolveComponentFactory(). Use the resulting ComponentFactory. create() method to create a component of that type.

What are the elements that we can use in Angluar templates?

This template uses typical HTML elements like <h2> and <p> . It also includes Angular template-syntax elements, *ngFor , {{hero.name}} , (click) , [hero] , and <app-hero-detail> . The template-syntax elements tell Angular how to render the HTML to the screen, using program logic and data.


2 Answers

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);
  });
}
like image 124
Linksonder Avatar answered Oct 22 '22 22:10

Linksonder


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 { }
like image 35
Ryang MinHo Avatar answered Oct 22 '22 20:10

Ryang MinHo