2016-11-10 8 views
7

動的コンポーネントを作成するために、Angular 2 APIのComponentResolverDynamicComponentResolverを見てきましたが、私はそれらのAPIとは異なる点があります。ng2 - テンプレートに基づいて動的にコンポーネントを作成する

クラス名の文字列に基づいてコンポーネントを作成する方法はありますか?

たとえば、構成可能なグラフダッシュボードを作成します。

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

どこtypeです:私は、JSONとしてこのデータをロードすると、各ユーザーのレイアウトは、彼らがここで2倍折れ線グラフにしたい旨、データベースに格納され、そこに3倍棒グラフなどは

それは何かのように見えます私が反射的に作成したいコンポーネントのクラス名。

これまでのところ、私は次のようしている:

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の必要性を排除することです。どのようにして、そのクラスへの参照を持たずに文字列に基づいてこのクラスを反映させることができますか?

答えて

9

アップデート2:

クラス名とコメントのバージョンで言及@estusとしては縮小では動作しません。

export LineChartComponent { 
    static key = "LineChartComponent"; 
} 

をして、などのユニークなこのkeyを使用します。それは縮小して作業を行うには、

1)あなたのentryComponents等それぞれの上にいくつかの静的なキーを追加することができます。

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:

ここcomponent`sクラス名

からのバージョンがあります
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 Example

+0

に感謝しなければならないが、このアプローチは私に壊れやすいと思われること。コンポーネントファクトリのレジストリがAngularによって公開されていない場合は、セレクタよりもクラス名を使用したいと思います。質問は、角型の質問よりもTypescriptの質問になります。つまり、文字列 "MyComponent"を使用して型MyComponentをインスタンス化する方法 – parliament

+0

うわー、それは私が笑にコメントする前に速い更新でした。新しいバージョンのplnkrを更新してもらえますか?私はリンクが両方とも同じであると思います。あなたはおそらくそれをフォークする必要があります – parliament

+0

私はコードを追加しました – yurzui

1

それは、輸入を反復処理することも可能です:

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

+0

誠に申し訳ありません – parliament

関連する問題