gpt4 book ai didi

javascript - 动态加载现有组件 Angular 2 Final Release

转载 作者:数据小太阳 更新时间:2023-10-29 03:49:07 26 4
gpt4 key购买 nike

我正在尝试在最终版本 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?

它看起来更适合那个场景,我只需要加载组件并设置一个名为模型的@Input。

有一件事,当我尝试时,我必须为每个组件动态创建一个模块,然后将组件添加到其中。但后来我遇到了问题,说该组件被设置在多个模块中,尝试在某个地方删除一个不起作用。

显示的代码的主要部分,我从这个链接获得:http://blog.lacolaco.net/post/dynamic-component-creation-in-angular-2-rc-5/

并做了一些改变。

Update

我设法使它工作,使用以下方法:

创建方法已更改为

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 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;
}

在这种情况下,我们必须在模块装饰器中的 declarationsentryComponents 属性中定义动态组件

@NgModule({
imports: [ BrowserModule ],
declarations: [ AppComponent, DynamicComponent ],
entryComponents: [DynamicComponent],
bootstrap: [ AppComponent ]
})
export class AppModule { }

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);
});
});
}
}

Plunker Example

希望对你有帮助!

关于javascript - 动态加载现有组件 Angular 2 Final Release,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/39678963/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com