Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Resolve Type<> of component from string in angular2

Is it possible to get type of component (Type<T>) from string value? Smth like:

let typeStr: string = 'MyComponent';
let type: any = resolveType(typeStr); // actual type
like image 500
Leonid Bor Avatar asked Mar 22 '17 10:03

Leonid Bor


People also ask

How to resolve a dynamic component in angular?

We have seen how Angular resolves dynamic components. The moduleProviderDef function is used to configure a provider for the Angular dependency injection framework. This is where ComponentFactory -s of dynamic components are passed to ComponentFactoryResolver class for resolution of a component's factory during runtime.

How do I pass a string to a component in angular?

Passing a string value to a component from its class: Here, the message variable will get its value either from the constructor of the class or by using angular event bindings (user inputs). Example: It is the simplest way of passing a string to a component.

What is a component in angular?

Understanding Components. In AngularJS, a Component is a special kind of directive that uses a simpler configuration which is suitable for a component-based application structure. This makes it easier to write an app in a way that's similar to using Web Components or using the new Angular's style of application architecture.

What is the use of resolves in angular controller?

It also makes the controller's code much cleaner in contrast to fetching data inside the controller. Load only important data in resolves to render main parts of the page immediately and fetch all other data, asynchronously. In Angular1, we could see the following code to define resolves in router (ui-router):


Video Answer


2 Answers

Just in case anyone stumbles across this question like me. It is possible without maintaining a registry.

Full credit goes to yurzui for his solution.

Just a copy from there:

import { Type } from '@angular/core';

@Input() comp: string;
...
const factories = Array.from(this.resolver['_factories'].keys());
const factoryClass = <Type<any>>factories.find((x: any) => x.name === this.comp);
const factory = this.resolver.resolveComponentFactory(factoryClass);
const compRef = this.vcRef.createComponent(factory);
like image 67
Vulcano Avatar answered Oct 14 '22 02:10

Vulcano


You can't do that without maintaining a "registry" for your classes.

interface Component { }

type ComponentClass = { new (): Component };

const REGISTRY = new Map<string, ComponentClass>();

function getTypeFor(name: string): ComponentClass {
    return REGISTRY.get(name);
}

As for how to add entries to this REGISTRY, you have a few options, here are two:

(1) Manually add it after every class definition:

class ComponentA implements Component { ... }
REGISTRY.set("ComponentA", ComponentA);

Or make a function for it:

function register(cls: ComponentClass): void {
    REGISTRY.set(cls.name, cls);
}

class ComponentA implements Component { ... }
register(ComponentA);

(2) Use a decorator:
Just use the above register function as a decorator:

@register
class ComponentA implements Component { ... }
like image 41
Nitzan Tomer Avatar answered Oct 14 '22 04:10

Nitzan Tomer