[英]Load existing components dynamically Angular 2 Final Release
我正在嘗試在最終版本2.0.0中動態加載組件。
使用RC5我使用以下代碼加載:
創建一個指令來加載控件:
import {
CheckboxComponent, CheckboxListComponent,DatePickerComponent
} from '../components/';
@Directive({
selector: '[ctrl-factory]'
})
export class ControlFactoryDirective implements OnChanges {
@Input() model: any;
constructor(private vcRef: ViewContainerRef, private resolver: ComponentResolver) {
}
create(cp) {
this.resolver.resolveComponent(cp)
.then(factory => {
const injector = ReflectiveInjector.fromResolvedProviders([], this.vcRef.parentInjector);
this.vcRef.createComponent(factory, 0, injector, []);
let ch = this.vcRef.createComponent(factory, 0, injector, []).instance;
ch.model = this.model;
});
}
ngOnChanges() {
if (!this.model) return;
switch (this.model.type) {
case 'checkbox':
this.create(CheckboxComponent);
break;
case 'checkboxlist':
this.create(CheckboxListComponent);
break;
case 'datepicker':
this.create(DatePickerComponent);
break;
default:
break;
}
}
}
然后在我的頁面中加載該指令,如下所示:
<div ctrl-factory *ngFor="let child of page.childrens" [model]="child"></div>
但是從rc5更新到2.0.0最終版本后,解析器不再存在,被編譯器取代。
我發現大量的地方顯示如何使用不同的代碼加載它,但所有那些太復雜,我無法使其工作。
以此為例: 我如何使用/創建動態模板來使用Angular 2.0編譯動態組件?
它看起來更具體到那個場景,我只需要加載組件並設置一個名為model的@Input。
我嘗試的一件事是我必須為每個組件動態創建一個模塊,然后將組件添加到它。 但后來我遇到的問題是該組件被設置在多個模塊中,嘗試在某些地方刪除不起作用。
顯示的代碼的主要部分,我從這個鏈接: http : //blog.lacolaco.net/post/dynamic-component-creation-in-angular-2-rc-5/
並做了一些改變。
更新
我設法使用以下方法使其工作:
create方法已更改為
private create(cp) {
@NgModule({
imports: [BrowserModule, ControlsModule],
declarations: []
})
class DynamicModule {}
this.compiler.compileModuleAndAllComponentsAsync(DynamicModule)
.then(({componentFactories}) => {
const compFactory = componentFactories.find(x => x.componentType === cp);
const injector = ReflectiveInjector.fromResolvedProviders([], this.vcRef.parentInjector);
const cmpRef = this.vcRef.createComponent(compFactory, 0, injector, []);
cmpRef.instance.model = this.model;
});
}
我找到的大多數地方,設置創建組件並將其設置為DynamicModule,問題是當你已經在另一個模塊中聲明相同的組件時,angular會抱怨。 在我的情況下,解決方案是導入我的ControlsModule,我的所有控件都被導出。
更新
NgComponentOutlet是在4.0.0-beta.3中引入的.https ://github.com/angular/angular/commit/8578682
即將推出的NgComponentOutlet
我看到兩個選項:
1)使用ComponentFactoryResolver 。
它使用已經生成的工廠,代碼如下所示:
constructor(private vcRef: ViewContainerRef, private resolver: ComponentFactoryResolver) { }
create(comp) {
const factory = this.resolver.resolveComponentFactory(comp);
const compRef = this.vcRef.createComponent(factory);
(<any>compRef).instance.model = this.model;
}
在這種情況下,我們必須在模塊的decorator中的declarations
和entryComponents
屬性中定義動態組件
@NgModule({
imports: [ BrowserModule ],
declarations: [ AppComponent, DynamicComponent ],
entryComponents: [DynamicComponent],
bootstrap: [ AppComponent ]
})
export class AppModule { }
2)使用編譯器
在這種情況下,我們只能使用compiler.compileModuleAndAllComponentsAsync
運行模塊compiler.compileModuleAndAllComponentsAsync
,然后從componentFactories數組中查找組件。 您的指令可能如下所示:
constructor(private vcRef: ViewContainerRef, private loader: DynamicLoaderService) { }
create(comp) {
this.loader.createComponentFactory(comp).then(factory => {
const compRef = this.vcRef.createComponent(factory);
(<any>compRef).instance.model = this.model;
})
}
DynamicLoaderService
是一個加載和存儲組件工廠的全局服務。
@Injectable()
export class DynamicLoaderService {
constructor(protected compiler: Compiler) {}
private resolveCompHelper$ = new Subject<any>();
private cache = new Map<string, ComponentFactory<any> | number>();
public createComponentFactory(type: string) : Promise<ComponentFactory<any>> {
let factory = this.cache.get(type);
// if factory has been already loading
if(factory === 1) {
return new Promise((resolve) => {
// waiting compilation of factory
const subscriber = this.resolveCompHelper$.subscribe((data) => {
if(type !== data.type) return;
subscriber.unsubscribe();
resolve(data.factory);
});
});
}
// factory exists in cache
if (factory) {
return new Promise((resolve) => resolve(factory));
}
const comp = typeMap[type];
// factory startes loading
this.cache.set(type, 1);
return new Promise((resolve) => {
this.compiler.compileModuleAndAllComponentsAsync(createComponentModule(comp))
.then((moduleWithFactories: ModuleWithComponentFactories<any>) => {
factory = moduleWithFactories.componentFactories
.find(x => x.componentType === comp);
this.cache.set(type, factory);
this.resolveCompHelper$.next({ type, factory});
resolve(factory);
});
});
}
}
希望它能幫到你!
根據指令看到這個選項對我很有用,但我根據組件找到了符合我需求的選項: https : //www.ag-grid.com/ag-grid-angular-aot-dynamic-components /
快樂的編碼!
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.