9

I know how to init components using ComponentFactoryResolver.resolveComponentFactory(AComponentType)

but the method expects a Type, while in my code I have the name of the type as a string.

In the Angular API is there a method to resolve by string? If not, how can I convert a string to a Type in TypeScript?

In case that none of the above is possible I will resort to a map but it's not so straightforward as the components I need to instantiate will come from remotely fetched UMD angular component library.

I. Ahmed
  • 2,438
  • 1
  • 12
  • 29
Cec
  • 1,726
  • 3
  • 18
  • 31
  • 1
    Possible duplicate of [How to get a class from a string in TypeScript/JavaScript in an Angular 2 application?](https://stackoverflow.com/questions/39863007/how-to-get-a-class-from-a-string-in-typescript-javascript-in-an-angular-2-applic) – ochs.tobi Mar 08 '18 at 08:09
  • https://stackoverflow.com/questions/40528592/ng2-dynamically-creating-a-component-based-on-a-template – yurzui Mar 08 '18 at 08:11
  • You should take a look to this: https://angular.io/guide/dynamic-component-loader – ADreNaLiNe-DJ Mar 08 '18 at 08:23

2 Answers2

5

You can do the following:

const classesMap = {
  AComponentType: AComponentType,
  BComponentType: BComponentType
}

And then:

CreateDynamicComponent(typeName: string) {
    ...
    const componentFactory = ComponentFactoryResolver.resolveComponentFactory(classesMap[typeName].prototype.constructor)
    ...
}
Tim Diekmann
  • 7,755
  • 11
  • 41
  • 69
Stanislav Dontsov
  • 1,591
  • 11
  • 24
2

I had the same problem, where i need to use a string to select what component to build. After some digging I created a list of the components that is added to the NgModuleexport and entryComponents lists.

template-components.ts

export const TEMPLATE_COMPONENTS: Type<any>[] = [
    Temp1Component,
    Temp2Component
  ]

in my NgModule class I just add TEMPLATE_COMPONENTS to both exports and entryComponents

In the component with the ComponentFactoryResolver you generate a list of Types, with the same string as a key.

let templateTypes: { [name: string]: Type<{}> } = 
    TEMPLATE_COMPONENTS.reduce((p, c) => { p[c.name] = c; return p }, {})

// templateTypes = {'Temp1Component':Temp1Component,...}

this.componentFactoryResolver.resolveComponentFactory(templateTypes[string]);

This means that you only have to add the components to one place, simplifying adding more components.

Its probably possible to skip the whole TEMPLATE_COMPONENTSin a separate list step and get the list directly from the NgModuleclass, but that will be sometime in the future.

Alexolo
  • 198
  • 2
  • 13