Context - I'm trying to create a custom dropdown that can contain a number of components. I could accomplish this via the
<ng-content>
import { Component } from '@angular/core';
import { MyDropdown } from './MyDropdown';
@Component({
selector: 'my-app',
template: `
<my-dropdown [contentModels]="dropdownContentModels"></my-dropdown>
`
})
export class Main {
dropdownContentModels: any[];
constructor() {
var someComponentModel = {selector: 'some-component', text: 'some'};
var otherComponentModel = {selector: 'other-component', text: 'other'};
this.dropdownContentModels = [someComponentModel, otherComponentModel];
}
}
import { Component } from '@angular/core';
import { InjectComponent } from './InjectComponent';
@Component({
selector: 'my-dropdown',
inputs: ['contentModels'],
directives: [InjectComponent],
template: `
<div class="btn-group" dropdown>
<button type="button" dropdownToggle>My Dropdown</button>
<div class="dropdown-menu" role="menu">
<inject-component *ngFor="let item of contentModels" [model]="item"></inject-component>
</div>
</div>
`
})
export class MyDropdown {
contentModels: any[];
}
import { Component, DynamicComponentLoader, Injector } from '@angular/core';
@Component({
selector: 'inject-component',
inputs: ['model'],
template: `
<div #toreplace></div>
`,
providers: [DynamicComponentLoader, Injector]
})
export class InjectComponent {
model: any;
constructor(private dcl: DynamicComponentLoader, private injector: Injector) {}
ngOnInit() {
this.dcl.loadAsRoot(this.createWrapper(), '#toreplace', this.injector);
}
createWrapper(): any {
var model = this.model;
@Component({
selector: model.selector + '-wrapper',
template: '<' + model.selector + ' [model]="model"></' + model.selector + '>'
})
class Wrapper {
model: any = model;
}
return Wrapper;
}
}
import { Component, ComponentResolver, ViewChild, ViewContainerRef,
ComponentFactory, ComponentRef } from '@angular/core';
@Component({
selector: 'inject-component',
inputs: ['model'],
template: `
<div #toreplace></div>
`
})
export class InjectComponent {
model: any;
@ViewChild('toreplace', {read: ViewContainerRef}) toreplace;
componentRef: ComponentRef<any>;
constructor(private resolver: ComponentResolver) {}
ngOnInit() {
this.resolver.resolveComponent(this.createWrapper()).then((factory:ComponentFactory<any>) => {
this.componentRef = this.toreplace.createComponent(factory);
});
}
createWrapper(): any {
var model = this.model;
@Component({
selector: model.selector + '-wrapper',
directives: [ model.directives ],
template: '<' + model.selector + ' [model]="model"></' + model.selector + '>'
})
class Wrapper {
model: any = model;
}
return Wrapper;
}
}
You can use the new .createComponent()
function.
import {ComponentRef, Injectable, Component, Injector, ViewContainerRef, ViewChild,ComponentResolver, DynamicComponentLoader} from '@angular/core';
export class InjectComponent {
@ViewChild('toreplace', {read: ViewContainerRef}) toreplace;
constructor(private dcl: DynamicComponentLoader, injector: Injector,private resolver: ComponentResolver) {}
...
this.resolver.resolveComponent((this.createWrapper()).then((factory:ComponentFactory<any>) => {
this.cmpRef = this.theBody.createComponent(factory)
});
and remove providers: [DynamicComponentLoader, Injector]
Here's an example plunker that uses DynamicComponentLoader (in app.component.ts): http://plnkr.co/edit/dVfc49AHHVwgws44ow4D?p=preview