上下文 - 我正在尝试创建一个可以包含许多组件的自定义下拉列表。我可以通过<ng-content>
标签完成此操作,但我的团队固执地坚持认为他们不喜欢这样。他们希望能够几乎完全通过打字稿代码来实例化这个下拉列表。
我想我可以通过DynamicComponentLoader实现这一点,但不幸的是,我发现的所有好教程都使用了loadIntoLocation()函数,现在它已经消失了。所以我尝试使用loadAsRoot()函数,但它不起作用。
这是我正在尝试做的事情:
Main.ts:
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];
}
}
MyDropdown.ts:
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[];
}
InjectComponent.ts:
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;
}
}
但是我得到了运行时异常“EXCEPTION:错误:未捕获(在承诺中):只能添加到TokenMap!令牌:Injector”
更新! (感谢echonax):
InjectComponent.ts:
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;
}
}
答案 0 :(得分:6)
您可以使用新的.createComponent()
功能。
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)
});
并删除providers: [DynamicComponentLoader, Injector]
以下是使用DynamicComponentLoader(在app.component.ts中)的示例plunker:https://plnkr.co/edit/azoGdAUvDvCwJ3RsPXD6?p=preview