我目前正在获取一个数组(在resourceTypes下面的代码中)和一个ngSwitch。正如您所看到的,根据TypeName,我创建了一种不同类型的组件/指令(config-resource-editor或mvc-resource-editor或...)。但是我不喜欢这个代码,因为当我创建更多的资源编辑器时,我总是要修改这个代码等。我如何重构代码,这样我就可以根据类型创建正确的资源编辑器,而不需要ng-switch。 我查看了ng-content,我想我必须对它做一些事情,但我没有看到它。
TL; DR:我如何重构下面的代码,所以我不再需要使用ngSwitch,而是将类型“耦合”到组件中。
<div *ngFor="let aType of resourceTypes; let i = index" role="tabpanel" class="tab-pane" [ngClass]="{'active': i==0}" [attr.id]="aType.Name">
<span *ngSwitch="aType.Name">
{{aType.Name}} tab content here
<config-resource-editor [application]="application" ngSwitchWhen="Config" template></config-resource-editor>
<mvc-resource-editor [application]="application" ngSwitchWhen="MVC" template></mvc-resource-editor>
<other-resource-editor [application]="application" ngSwitchWhen="Other" template></other-resource-editor>
<wcf-resource-editor [application]="application" ngSwitchWhen="WCF" template></wcf-resource-editor>
<web-resource-editor [application]="application" ngSwitchWhen="Web" template></web-resource-editor>
<webapi-resource-editor [application]="application" ngSwitchWhen="WebAPI" template></webapi-resource-editor>
</span>
</div>
如果事情不明确,请随时提出。
提前致谢
答案 0 :(得分:2)
您可以创建一个包装器组件并使用@ViewChild来摆脱切换案例。
你的包装器看起来如下:
@Component({
selector: 'my-wrapper',
template: `<div #target></div>`
})
export class MyWrapper {
@ViewChild('target', {read: ViewContainerRef}) target;
cmpRef: ComponentRef<Component>;
currentComponent: Component;
private isViewInitialized: boolean = false;
constructor(
private componentFactoryResolver: ComponentFactoryResolver,
private cdRef: ChangeDetectorRef,
private wrapperService: WrapperService
){}
updateComponent() {
if (!this.currentComponent) {
return;
}
if (!this.isViewInitialized) {
return;
}
if (this.cmpRef) {
this.cmpRef.destroy();
}
let factory = this.componentFactoryResolver.resolveComponentFactory(this.currentComponent);
this.cmpRef = this.target.createComponent(factory);
}
ngAfterViewInit() {
this.cdRef.detectChanges();
this.isViewInitialized = true;
this.currentComponentSubscription = this.wrapperService.getCurrentComponent().subscribe(c => {
this.currentComponent = c;
if (c) {
this.updateComponent();
}
});
}
ngOnDestroy() {
if (this.cmpRef) {
this.cmpRef.destroy();
}
if(this.currentComponentSubscription){
this.currentComponentSubscription.unsubscribe()
}
}
}
创建一个WrapperService并为当前组件编写一个getter / setter,并注意getter应该返回一个BehaviorSubject:
private _currentComponent: BehaviorSubject<Component> = new BehaviorSubject(null);
getCurrentComponent(): BehaviorSubject<Component> {
return this._currentComponent;
}
setCurrentComponent(value: Component) {
this._currentComponent.next(value);
}
使用MyWrapper组件的选择器代替ngSwitch,并使用父组件中定义resourceTypes的包装器服务设置当前组件。
您还需要将附加/分离的组件添加到@NgModules中的entryComponents:
@NgModule({
entryComponents: <array of components>
})
注意:在设置_currentComponent时,您需要提供对组件的引用而不是字符串。
致谢:@Gunter我也提到了他的例子来帮助我。