我正在尝试在最终版本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最终版本后,解析器不再存在,被编译器取代.
我发现大量的地方显示如何使用不同的代码加载它,但所有那些太复杂,我无法使其工作.
以此为例:How can I use/create dynamic template to compile dynamic Component with Angular 2.0?
它看起来更具体到那个场景,我只需要加载组件并设置一个名为model的@Input.
我尝试的一件事是我必须为每个组件动态创建一个模块,然后将组件添加到它.但后来我遇到的问题是该组件被设置在多个模块中,尝试在某些地方删除不起作用.
显示的代码的主要部分,我从这个链接:http://blog.lacolaco.net/post/dynamic-component-creation-in-angular-2-rc-5/
并做了一些改变.
Update
我设法使用以下方法使其工作:
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中引入的
Coming soon 07001
我看到两个选项:
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中的声明和entryComponents属性中定义动态组件
@NgModule({
imports: [ browserModule ],
declarations: [ AppComponent, DynamicComponent ],
entryComponents: [DynamicComponent],
bootstrap: [ AppComponent ]
})
export class AppModule { }
> Dynamically Creating Components With Angular 2.0
> Plunker Example
2)使用编译器
在这种情况下,我们只能使用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);
});
});
}
}
希望它能帮到你!
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 [email protected] 举报,一经查实,本站将立刻删除。