Sivvio
Sivvio

Reputation: 297

How to load dynamically a component in angular 4 in the parent component

I'm creating template components to be loaded in the parent component depending on what response I get from the server. I'll give you a brief example of what I'm trying to do in pseudo code.

This is my html parent component:

<div class="parent-container">
    <div *ngIf="template1"> (load template1.component) </div>
    <div *ngIf="template2"> (load template2.component) </div>
    etc...
</div>

then I would have the different components (for sake of brevity I will just list one)

<div class="child-container">
    <div> {{userName}} </div>
    <div> {{contactNo}} </div>
    <div> {{address}} </div>
</div>

so on ngInit the parent makes an http request to the server and gets a value. Depends on the value in the parent, I should be able to load the child template into the parent and display it. So, once loaded, the page would look like this:

<div class="parent-container">
    <div class="child-container">
        <div> {{userName}} </div>
        <div> {{contactNo}} </div>
        <div> {{address}} </div>
    </div>
</div>

Is it possible in angular? How can i create it? Thanks

[edit]

I implemented what dee zg suggested, this is the code:

@ViewChild(HostDirective) host: HostDirective;

OnNgInit(){}

//switch will be a response from a server 
selector(switch){
    switch(switch) { 
       case 'component1': { 
         this.loadComponent(Component1);
         break; 
      }  
      default: { 

         break; 
      } 
   } 

  }

  loadComponent(component){   


    var componentFactory = this._componentFactoryResolver.resolveComponentFactory(component);
    var viewContainerRef = this.host;
    this.viewContainerRef.clear();
    var componentRef = this.viewContainerRef.createComponent(componentFactory);

    (componentRef.instance);

  }

this is what is inside my host

import { Directive, ViewContainerRef } from '@angular/core';

@Directive({
  selector: '[host]',
})
export class HostDirective {
  constructor(public viewContainerRef: ViewContainerRef) { }
}

and the html

<ng-template host></ng-template>

funny thing is that if whatever is inside loadComponent will be loaded into OnInit, then it will work. If I call it from loadComponent I will get that host is undefined.

Upvotes: 2

Views: 10682

Answers (2)

tlt
tlt

Reputation: 15221

in template:

<ng-template #yourComponentHost></ng-template>

in component:

@ViewChild('yourComponentHost', { read: ViewContainerRef })
  yourComponentHost;
.
.
.
const componentFactory = this._componentFactoryResolver.resolveComponentFactory(YourComponentType1);
    const viewContainerRef = this.yourComponentHost;
    viewContainerRef.clear();
    const componentRef = viewContainerRef.createComponent(componentFactory);

    const yourComponentType1Instance = (<YourComponentType1>componentRef.instance);

From here, you have an access to your component through yourComponentType1Instance. Of course, you'll do your own switch logic in resolveComponentFactory to use component you need based on conditions you want.

Upvotes: 4

Wandrille
Wandrille

Reputation: 6811

It's a little bit confusing what you are looking for. Because with your problem, why don't you create component for you child.

<div class="parent-container">
    <div *ngIf="template1"> <template1 [myData]="myData"></template1> </div>
    <div *ngIf="template2"> <template2 [myData]="myData"></template2> </div>
    etc...
</div>

Upvotes: 1

Related Questions