簡體   English   中英

ng2 - 基於模板動態創建組件

[英]ng2 - dynamically creating a component based on a template

我一直在研究用於創建動態組件的ComponentResolverDynamicComponentResolver的 Angular 2 API,但我的想法與這些 API 提供的有所不同。

NG2 中是否有任何方法可以根據其類名字符串創建組件?

例如,我正在構建一個可配置的圖表儀表板。 每個用戶的布局都存儲在數據庫中,說明他們在這里需要 2x 折線圖,在那里需要 3x 條形圖,等等。

當我將此數據加載為 json 時,它看起來像:

user.charts = [
     { type: 'LineChartComponent', position: ... }
     { type: 'BarChartComponent', position: ... }
];

其中type是我想反射性創建的組件的類名。

到目前為止,我有以下幾點:

 this.chartMap = {
    'LineChartComponent': LineChartComponent
 };

let config = this.configuration;
let chartComponentType = this.chartMap[config.type];
let factory = this.componentFactory.resolveComponentFactory(chartComponentType);
let component = factory.create(this.injector);
component.instance.configuration = config;
this.chartContainer.insert(component.hostView);

但整個想法是消除對chartMap的需要。 如何在沒有引用類型的情況下基於字符串反射性地創建此類?

更新2:

正如@estus 在帶有 className 的評論版本中提到的那樣不適用於縮小。 要做到與縮小一起工作,您可以

1) 在每個entryComponents上添加一些靜態鍵,例如:

export LineChartComponent {
  static key = "LineChartComponent";
}

然后將此key用作唯一key

const factoryClass = <Type<any>>factories.find((x: any) => x.key === compClassKey);

2)創建一個字典

export const entryComponentsMap = {
  'comp1': Component1,
  'comp2': Component2,
  'comp3': Component3
};

然后

const factory = this.resolver.resolveComponentFactory(entryComponentsMap.comp1);

更新1:

這是組件類名的版本

const factories = Array.from(this.resolver['_factories'].keys());
const factoryClass = <Type<any>>factories.find((x: any) => x.name === compClassName);
const factory = this.resolver.resolveComponentFactory(factoryClass);

舊版本

您可以通過組件選擇器獲取工廠,但您必須使用私有屬性。

它可能看起來像:

const factories = Array.from(this.resolver['_factories'].values());
const factory = factories.find((x: any) => x.selector === selector);

Plunker 示例

也可以遍歷import

import * as possibleComponents from './someComponentLocation'
...
let inputComponent;
for(var key in possibleComponents ){
      if(key == componentStringName){
          inputComponent = possibleComponents[key];
          break;
      }
 }

更新:或者只是:-)

let inputComponent = possibleComponents[componentStringName]

然后您可以創建組件實例,例如:

if (inputComponent) {
    let inputs = {model: model};
    let inputProviders = Object.keys(inputs).map((inputName) => { return { provide: inputName, useValue: inputs[inputName] }; });
    let resolvedInputs = ReflectiveInjector.resolve(inputProviders);
    let injector: ReflectiveInjector = ReflectiveInjector.fromResolvedProviders(resolvedInputs, this.dynamicInsert.parentInjector);
    let factory = this.resolver.resolveComponentFactory(inputComponent as any);
    let component = factory.create(injector);
    this.dynamicInsert.insert(component.hostView);
}

請注意,組件必須在 @NgModule entryComponents 中

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM