上下文 - 我正在尝试创建一个可以包含多个组件的自定义下拉列表。我可以通过以下方式完成此任务<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[];
}
注入组件.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;
}
}
但我收到运行时异常“异常:错误:未捕获(承诺中):只能添加到 TokenMap!令牌:注入器”
更新! (感谢 echonax):
注入组件.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;
}
}