0

For example, I have a list of options in one Component, where clicking on one renders a Component dynamically based on the user's selection. This is how I image it would be done:

List Component

import { Component } from '@angular/core';
@Component({
    selector: 'list-component',
    templateUrl: `
        <ul>
            <li *ngFor="let item from list" (click)="onClick(item)">{{item.name}}</li>
        </ul>
    `
})
export class ListComponent {

    list = [
        {name: 'Component1'},
        {name: 'Component2'},
        {name: 'Component3'}
    ]

    constructor(private _listService: ListService) {

    }

    onClick(item) {
        this._listService.renderComponent(item);
    }
}

Render Component

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

@Component({
    selector: 'render-component',
    templateUrl: `
        <div #dynamicComponent></div>
    `
})
export class RenderComponent {

    @ViewChild('dynamicComponent', { read: ViewContainerRef })
    private dynamicComponent: any;

    constructor(
        private _listService: ListService,
        private resolver: ComponentFactoryResolver
    ) {

        this._listService.onRenderComponent.subscribe(item => {
            let componentReference;

            //TODO: Get Component by reference ???

            let componentFactory = this.resolver.resolveComponentFactory(componentReference);
            this.dynamicComponent.createComponent(componentFactory);

        })
    }
}

I've left the details about ListService but it is essentially a service that allows the two components to communicate.

I would prefer not to have references to components inside ListComponent like so:

import {Component1, Component2, Component3} from './otherComponents';

...

list = [
    {name: 'Component1', component: Component1},
    {name: 'Component2', component: Component2},
    {name: 'Component3', component: Component3}
]

...

this._listService.onRenderComponent.subscribe(item => {
    let componentReference = item.component;

    let componentFactory = this.resolver.resolveComponentFactory(componentReference);
    this.dynamicComponent.createComponent(componentFactory);

})

and let the ListService handle it.

So essentially, does angular provide methods for retrieving a Component based on some references such as selector, componentId or something along those line?

slim1801
  • 531
  • 3
  • 8
  • 19
  • See also http://stackoverflow.com/questions/40115072/how-to-load-component-dynamically-using-component-name-in-angular2 – yurzui Oct 23 '16 at 07:08

1 Answers1

1

If you using Angular 2.0 final (which I don't think you are), you can actually resolve the component via a selector.

 const compFactory = this.factory.componentFactories.find(x => x.selector === 'my-component-selector');
    const injector = ReflectiveInjector.fromResolvedProviders([], this.vcRef.parentInjector);
    const cmpRef = this.vcRef.createComponent(compFactory, this.vcRef.length, injector, []);

I have a minimalist example of dynamic component creation here

Community
  • 1
  • 1
Stephen Paul
  • 37,253
  • 15
  • 92
  • 74
  • 1
    Seems he doesn't use `Compiler` He prefers to use `ComponentFactoryResolver` together with `entryComponents` or `ANALYZE_FOR_ENTRY_COMPONENTS` provider for dynamic component creation. – yurzui Oct 23 '16 at 07:11
  • Fair enough. Has that been deprecated though? I can't tell. – Stephen Paul Oct 23 '16 at 07:45