ปรับปรุง
ตัวอย่าง Angular 5 StackBlitz
ปรับปรุง
ngComponentOutlet
ถูกเพิ่มใน 4.0.0-beta.3
ปรับปรุง
มีNgComponentOutlet
ความคืบหน้าในการทำงานที่ทำสิ่งที่คล้ายกันhttps://github.com/angular/angular/pull/11235
RC.7
ตัวอย่าง Plunker RC.7
// Helper component to add dynamic components
@Component({
selector: 'dcl-wrapper',
template: `<div #target></div>`
})
export class DclWrapper {
@ViewChild('target', {read: ViewContainerRef}) target: ViewContainerRef;
@Input() type: Type<Component>;
cmpRef: ComponentRef<Component>;
private isViewInitialized:boolean = false;
constructor(private componentFactoryResolver: ComponentFactoryResolver, private compiler: Compiler) {}
updateComponent() {
if(!this.isViewInitialized) {
return;
}
if(this.cmpRef) {
// when the `type` input changes we destroy a previously
// created component before creating the new one
this.cmpRef.destroy();
}
let factory = this.componentFactoryResolver.resolveComponentFactory(this.type);
this.cmpRef = this.target.createComponent(factory)
// to access the created instance use
// this.compRef.instance.someProperty = 'someValue';
// this.compRef.instance.someOutput.subscribe(val => doSomething());
}
ngOnChanges() {
this.updateComponent();
}
ngAfterViewInit() {
this.isViewInitialized = true;
this.updateComponent();
}
ngOnDestroy() {
if(this.cmpRef) {
this.cmpRef.destroy();
}
}
}
ตัวอย่างการใช้งาน
// Use dcl-wrapper component
@Component({
selector: 'my-tabs',
template: `
<h2>Tabs</h2>
<div *ngFor="let tab of tabs">
<dcl-wrapper [type]="tab"></dcl-wrapper>
</div>
`
})
export class Tabs {
@Input() tabs;
}
@Component({
selector: 'my-app',
template: `
<h2>Hello {{name}}</h2>
<my-tabs [tabs]="types"></my-tabs>
`
})
export class App {
// The list of components to create tabs from
types = [C3, C1, C2, C3, C3, C1, C1];
}
@NgModule({
imports: [ BrowserModule ],
declarations: [ App, DclWrapper, Tabs, C1, C2, C3],
entryComponents: [C1, C2, C3],
bootstrap: [ App ]
})
export class AppModule {}
ดูเพิ่มเติมที่angular.io ตัวโหลดคอมโพเนนต์แบบไดนามิก
รุ่นที่เก่ากว่า xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx ที่เก่ากว่า
สิ่งนี้เปลี่ยนไปอีกครั้งใน Angular2 RC.5
ฉันจะอัปเดตตัวอย่างด้านล่าง แต่เป็นวันสุดท้ายก่อนวันหยุด
ตัวอย่าง Plunkerนี้สาธิตวิธีสร้างส่วนประกอบแบบไดนามิกใน RC.5
อัปเดต - ใช้ViewContainerRef .createComponent ()
เนื่องจากDynamicComponentLoader
เลิกใช้แล้วจึงต้องอัปเดตวิธีการอีกครั้ง
@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).then((factory:ComponentFactory<any>) => {
this.cmpRef = this.target.createComponent(factory)
// to access the created instance use
// this.compRef.instance.someProperty = 'someValue';
// this.compRef.instance.someOutput.subscribe(val => doSomething());
});
}
ngOnChanges() {
this.updateComponent();
}
ngAfterViewInit() {
this.isViewInitialized = true;
this.updateComponent();
}
ngOnDestroy() {
if(this.cmpRef) {
this.cmpRef.destroy();
}
}
}
ตัวอย่าง Plunker
RC.4 ตัวอย่างของ Plunker beta.17
อัปเดต - ใช้ loadNextToLocation
export class DclWrapper {
@ViewChild('target', {read: ViewContainerRef}) target;
@Input() type;
cmpRef:ComponentRef;
private isViewInitialized:boolean = false;
constructor(private dcl:DynamicComponentLoader) {}
updateComponent() {
// should be executed every time `type` changes but not before `ngAfterViewInit()` was called
// to have `target` initialized
if(!this.isViewInitialized) {
return;
}
if(this.cmpRef) {
this.cmpRef.destroy();
}
this.dcl.loadNextToLocation(this.type, this.target).then((cmpRef) => {
this.cmpRef = cmpRef;
});
}
ngOnChanges() {
this.updateComponent();
}
ngAfterViewInit() {
this.isViewInitialized = true;
this.updateComponent();
}
ngOnDestroy() {
if(this.cmpRef) {
this.cmpRef.destroy();
}
}
}
ตัวอย่าง Plunker beta.17
เป็นต้นฉบับ
ไม่แน่ใจทั้งหมดจากคำถามของคุณว่าความต้องการของคุณเป็นอย่างไร แต่ฉันคิดว่าสิ่งนี้ควรทำในสิ่งที่คุณต้องการ
Tabs
องค์ประกอบได้รับอาร์เรย์ของชนิดผ่านและจะสร้าง "แท็บ" สำหรับแต่ละรายการในอาร์เรย์
@Component({
selector: 'dcl-wrapper',
template: `<div #target></div>`
})
export class DclWrapper {
constructor(private elRef:ElementRef, private dcl:DynamicComponentLoader) {}
@Input() type;
ngOnChanges() {
if(this.cmpRef) {
this.cmpRef.dispose();
}
this.dcl.loadIntoLocation(this.type, this.elRef, 'target').then((cmpRef) => {
this.cmpRef = cmpRef;
});
}
}
@Component({
selector: 'c1',
template: `<h2>c1</h2>`
})
export class C1 {
}
@Component({
selector: 'c2',
template: `<h2>c2</h2>`
})
export class C2 {
}
@Component({
selector: 'c3',
template: `<h2>c3</h2>`
})
export class C3 {
}
@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;
}
@Component({
selector: 'my-app',
directives: [Tabs]
template: `
<h2>Hello {{name}}</h2>
<my-tabs [tabs]="types"></my-tabs>
`
})
export class App {
types = [C3, C1, C2, C3, C3, C1, C1];
}
ตัวอย่าง Plunker beta.15 (ไม่ขึ้นอยู่กับ Plunker ของคุณ)
นอกจากนี้ยังมีวิธีการส่งผ่านข้อมูลตามที่สามารถส่งผ่านไปยังองค์ประกอบที่สร้างขึ้นแบบไดนามิกเช่น ( someData
จะต้องผ่านเช่นtype
)
this.dcl.loadIntoLocation(this.type, this.elRef, 'target').then((cmpRef) => {
cmpRef.instance.someProperty = someData;
this.cmpRef = cmpRef;
});
นอกจากนี้ยังมีการสนับสนุนให้ใช้การฉีดพึ่งพากับบริการที่ใช้ร่วมกัน
สำหรับรายละเอียดเพิ่มเติมโปรดดูhttps://angular.io/docs/ts/latest/cookbook/dynamic-component-loader.html