受到Angular 2 dynamic tabs with user-click chosen components和Passing Input while creating Angular 2 Component dynamically using ComponentResolver的启发我试图更进一步,不仅让标签获得动态组件,而且标签的内容也包含动态组件。 从原始示例中,我使用了组件C1-C3作为选项卡,并希望将C4和C5用于部分。我知道实际标签没有任何样式/功能,但结构应该足以让我继续前进。 I made this.
//our root app component
import {Component, ComponentRef, Input, ViewContainerRef, ComponentResolver, ViewChild, Injectable, OnInit} from '@angular/core';
@Component({
selector: 'dcl-wrapper',
template: `<div #target></div>`
})
export class DclWrapper {
@ViewChild('target', {read: ViewContainerRef}) target;
@Input() type;
cmpRef:ComponentRef;
private isViewInitialized:boolean = false;
constructor(private resolver: ComponentResolver) {}
updateComponent() {
if(!this.isViewInitialized) {
return;
}
if(this.cmpRef) {
this.cmpRef.destroy();
}
this.resolver.resolveComponent(this.type.type).then((factory:ComponentFactory<any>) => {
this.cmpRef = this.target.createComponent(factory);
this.cmpRef.instance.info = this.type;
});
}
ngOnChanges() {
this.updateComponent();
}
ngAfterViewInit() {
this.isViewInitialized = true;
this.updateComponent();
}
ngOnDestroy() {
if(this.cmpRef) {
this.cmpRef.destroy();
}
}
}
@Component({
selector: 'child-dcl-wrapper',
template: `<div #target></div>`
})
export class ChildDclWrapper {
@ViewChild('target', {read: ViewContainerRef}) target;
@Input() type;
cmpRef:ComponentRef;
private isViewInitialized:boolean = false;
constructor(private resolver: ComponentResolver) {}
updateComponent() {
if(!this.isViewInitialized) {
return;
}
if(this.cmpRef) {
this.cmpRef.destroy();
}
this.resolver.resolveComponent(this.type.type).then((factory:ComponentFactory<any>) => {
this.cmpRef = this.target.createComponent(factory);
this.cmpRef.instance.info = this.type;
});
}
ngOnChanges() {
this.updateComponent();
}
ngAfterViewInit() {
this.isViewInitialized = true;
this.updateComponent();
}
ngOnDestroy() {
if(this.cmpRef) {
this.cmpRef.destroy();
}
}
}
@Component({
selector: 'c1',
template: `<h2>c1</h2><p>{{info.name}}</p>
<my-sections [sections]="section"></my-sections>`
})
export class C1 {
}
@Component({
selector: 'c2',
template: `<h2>c2</h2><p>{{info.name}}</p>
<my-sections [sections]="section"></my-sections>`
})
export class C2 {
}
@Component({
selector: 'c3',
template: `<h2>c3</h2><p>{{info.name}}</p>
<my-sections [sections]="section"></my-sections>`
})
export class C3 {
}
@Component({
selector: 'c4',
template: `<h2>c4</h2><p>{{info.name}}</p>`
})
export class C4 {
}
@Component({
selector: 'c5',
template: `<h2>c5</h2><p>{{info.name}}</p>`
})
export class C5 {
}
@Component({
selector: 'my-sections',
directives: [ChildDclWrapper],
template: `
<h3>Sections</h3>
<div *ngFor="let section of type.sections">
<child-dcl-wrapper [type]="section"></child-dcl-wrapper>
</div>
`
})
export class Sections {
@Input() sections;
}
@Component({
selector: 'my-tabs',
directives: [DclWrapper],
template: `
<h2>Tabs</h2>
<div *ngFor="let tab of tabs">
<dcl-wrapper [type]="tab"></dcl-wrapper>
</div>
`
})
export class Tabs {
@Input() tabs;
}
@Injectable()
export class AService {
info = [
{
name: "taco",
type: C1,
sections: [
{
name: "believe",
type: C4
},
{
name: "car",
type: C5
}
]
},
{
name: "pete",
type: C2,
sections: [
{
name: "repeat",
type: C4
},
{
name: "banana",
type: C5
}
]
},
{
name: "carl",
type: C3,
sections: [
{
name: "shotgun",
type: C4
},
{
name: "helmet",
type: C5
}
]
}
];
getServiceInfo() {
console.log("Bung.");
return this.info;
}
}
@Component({
selector: 'my-app',
directives: [Tabs],
providers: [AService],
template: `
<h1>Hello {{name}}</h1>
<my-tabs [tabs]="types"></my-tabs>
`
})
export class App extends OnInit {
types;
aService;
constructor(private aService: AService) {
this.aService = aService;
}
getInfo() {
console.log("beep");
this.types = this.aService.getServiceInfo();
}
ngOnInit() {
console.log("boop");
this.getInfo();
}
}
答案 0 :(得分:2)
我在您的代码中看到了几个错误。例如,您需要在以下代码中使用info.sections
而不是section
:
<my-sections [sections]="section"></my-sections>
应该是:
<my-sections [sections]="info.sections"></my-sections>
此外,您忘记添加Sections
指令,如下所示:
@Component({
selector: 'c1',
template: `<h2>c1</h2><p>{{info.name}}</p>
<my-sections [sections]="info.sections"></my-sections>`,
directives: [Sections] <== add this line
})
export class C1 {}
你可以使用一个DclWrapper
来做到这一点。
更新的plunkr在这里https://plnkr.co/edit/JRyqou9yC6LvSRrCR3eA?p=preview