Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Angular 5 - instantiate a component from its name as a string

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.

like image 237
Cec Avatar asked Mar 08 '18 08:03

Cec


People also ask

What is @component called in Angular?

The @Component decorator identifies the class immediately below it as a component class, and specifies its metadata. In the example code below, you can see that HeroListComponent is just a class, with no special Angular notation or syntax at all.

Can we pass component as input in Angular?

Firstly, we have to create a custom property to pass the data into a component. This can be done via input binding, which passes data from one component to another, generally from parent to child. This custom input binding is created by using the @Input() decorator.

How do I create a new component in Angular using Visual Studio code?

Create a new Angular application using ng new or open an existing one. Open the command prompt or terminal. Alternatively, if you have your Angular application open in an IDE such as Visual Studio Code, you can use the built-in terminal. The new component will get created in a new folder, inside the src/app directory.

How components are created in Angular?

To create a component using the Angular CLI: From a terminal window, navigate to the directory containing your application. Run the ng generate component <component-name> command, where <component-name> is the name of your new component.


2 Answers

You can do the following:

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

And then:

CreateDynamicComponent(typeName: string) {
    ...
    const componentFactory = ComponentFactoryResolver.resolveComponentFactory(classesMap[typeName].prototype.constructor)
    ...
}
like image 144
Stanisalv Dontsov Avatar answered Sep 21 '22 12:09

Stanisalv Dontsov


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.

like image 20
Alexolo Avatar answered Sep 22 '22 12:09

Alexolo