2

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.

8
  • Are you aware of which are the components you could actually load? Cause if so, then your current approach works. It's not the most elegant approach, but it works Commented Oct 5, 2017 at 16:23
  • yes I am, but I would like to have one if statement in which I will load whichever component the backend is telling me to. The parent component, depending on the response, will choose which template component to use for that case, and then parse the information to the html and render the component Commented Oct 5, 2017 at 16:34
  • edit: look at dee zg answer. ok, there's a way to load components dynamically inside a ng-template tag using ViewContainerRef and ComponentFactoryResolver , but you would still have to "declare" your dynamic components in you parent component decorator, give me some time and I can setup a plunker for you Commented Oct 5, 2017 at 17:01
  • what triggers your selector(switch)? Commented Oct 6, 2017 at 17:17
  • is basically a response from the server. so I do an http request to it, if I find the property of the response as "Component1" then it will go to switch, and so for the rest. For sake of brevity I omitted all the others, but it's just the same thing over and over Commented Oct 6, 2017 at 17:20

2 Answers 2

4

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.

Sign up to request clarification or add additional context in comments.

12 Comments

I'm facing an issue with this piece of code: (<YourComponentType1>componentRef.instance); <YourComponentType1>, I want it to be dynamic. I'm parsing the component through a method (so basically I will be parsing YourComponentType1, or 2 or 3), but if I parse it that way I get an error that says: Error: No component factory found for [object Object]. Did you add it to @NgModule.entryComponents? any idea how to resolve?
oh, yes, absolutely! components created with componentFactory must be added to entryComponents: angular.io/guide/dynamic-component-loader#resolving-components. Otherwise, angular would have no idea what YourComponentType1 actually is.
I did but same result. Debugging I found that whenever I parse yourcomponent1, it is an object (if instead I did it on ngInit it would be parsed as a component). so I parse yourcomponent1.constructor to initiate the component. what happens next is that this.yourComponentHost is undefined
hm...let me ask, just to be sure, what exactly do you mean by 'parse yourcomponent1?
if you're talking about switching between components you want to instantiate by string, then this might be useful: stackoverflow.com/questions/40062970/…
|
1

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>

Comments

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.