4

This is for the 2.1.0 Final release versions of Angular.

I'm trying to dynamically instantiate a component who's type is passed from a config JSON file. The best thing I can find is ComponentFactoryResolver, however all usages that I have found save one seem to be passing actual Type objects to the resolver.

Is there a way to get the Type from a string? Because presently, passing the type as a string gives me the error:

No component factory found for MyComponent

Relevant code:

StructureBuilder component:

private renderComponent(config:any) {
    let configComponents = config.components;
    if(config.hasOwnProperty('components') && configComponents.length){
        for(let i = 0, len = configComponents.length; i < len; i++){
            this.componentResolver.resolveComponentFactory(configComponents[i]);
        }
    }
}

where config.components is an array of strings that use the Type as a value.

And in the module definition (Structure.module.ts)

@NgModule({
    declarations: [
        MyComponent,
        StructureBuilder_Cmp
    ],
    entryComponents: [
        MyComponent
    ]
    //Etc...
});

As far as can tell with the sparse docs, this is exactly how you're supposed to do it.

If I change the dynamic string passed in from configComponents[i] to the actual imported type reference for MyComponent, it works.

So basically, the question is: Is there a way to use resolveComponentFactory with strings to resolve a component, and if not, is there way to get a Type reference from a string value?

7
  • Do you want to pass 'MyComponent' as string into resolveComponentFactory? Commented Oct 24, 2016 at 15:54
  • Yes, sorry that's what I mean. Commented Oct 24, 2016 at 15:55
  • Check this answer stackoverflow.com/questions/40115072/… Commented Oct 24, 2016 at 15:56
  • @yurzui the problem with that answer is that it uses private, internal properties of the resolver. Private things like that are subject to change in future versions, so that's really not a reliable solution. Commented Oct 24, 2016 at 16:45
  • Yes, you're right. This way you have to declare something like map = { "MyComponent": MyComponent } and use it Commented Oct 24, 2016 at 16:48

1 Answer 1

9

My solution for now is to do what I really wanted to avoid, which is maintaining a key/val registry.

let componentRegistry = {
    'SomeComp1': SomeComp1, 
    'SomeComp2': SomeComp2
}

And then call it with:

private renderComponent(config:any) {
    let configComponents = config.components;
    if(config.hasOwnProperty('components') && configComponents.length){
        for(let i = 0, len = configComponents.length; i < len; i++){
            let comp = configComponents[i];
            this.componentResolver.resolveComponentFactory(this.componentRegistry[comp]);
        }
    }
}
Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.