Skip to content

Instantly share code, notes, and snippets.

@arniebradfo
Last active May 27, 2021 19:14
Show Gist options
  • Save arniebradfo/2b163acbb51c5f0e7806acdd35906998 to your computer and use it in GitHub Desktop.
Save arniebradfo/2b163acbb51c5f0e7806acdd35906998 to your computer and use it in GitHub Desktop.
Get a Angular component by a string corresponding to its class name
/**
* @author http://bradford.digital
* @link https://stackoverflow.com/questions/42949647/resolve-type-of-component-from-string-in-angular2
*
* Keep a registry of key:value pairs that is the string name of a component and the Component reference
* The registry is stored in an exported const named COMPONENTREGISTRY
* Add to the registry by using the registerComponent() function as an adorner. example:
* @registerComponent
* @Component({...})
* export class AnExampleComponent {...}
* Get a component by its string name by calling COMPONENTREGISTRY.getTypeFor('AnExampleComponent')
* Or get it by its template name if your following general angular naming convention COMPONENTREGISTRY.getTypeFor('app-an-example')
*
* TODO: add the html template string without guessing like we are now?
* A class couuld be obtained by calling COMPONENTREGISTRY.getTypeFor('app-an-example')
**/
interface Component { }
type ComponentClass = { new(...any: any[]): Component };
class ComponentRegistry {
registry = new Map<string, ComponentClass>();
getTypeFor(name: string): ComponentClass {
if (name.match('-'))
name = this.getComponentNameFromTemplate(name);
let componentClass: ComponentClass = this.registry.get(name);
if (componentClass == null) throw new Error(`${name} was not found in the COMPONENTREGISTRY.registry`);
return componentClass;
}
getComponentNameFromTemplate(name: string): string {
const words: string[] = name.split('-');
words.splice(0, 1); // remove the prefix
for (let i = 0; i < words.length; i++) {
const capitalized = words[i].charAt(0).toUpperCase() + words[i].slice(1);
words.splice(i, 1, capitalized);
}
const componentName = words.join('') + 'Component';
return componentName;
}
register(cls: ComponentClass): void {
this.registry.set(cls.name, cls);
}
// registerTemplateString(cls: ComponentClass): void {
// let templateString = 'app-angular-component'; // how to get this from the ComponentClass reference?
// this.registry.set(templateString, cls);
// }
}
export const COMPONENTREGISTRY = new ComponentRegistry();
export function registerComponent(componentClass: ComponentClass): void {
COMPONENTREGISTRY.register(componentClass);
}
@Resington
Copy link

Hi, Thanks for sharing your code... I have integrated your typescript code into my angular project. While running the code, I am getting this error..." MySampleComponent was not found in the COMPONENTREGISTRY.registry at ComponentRegistry.getTypeFor " . Am I doing anything wrong. Do I need to Import MySampleComponent into ComponentRegistry. If so how should I do that? Thanks in advance...

@arniebradfo
Copy link
Author

@Resington I honestly don't remember how this works. This was written a long time ago and I was using Angular v3 (I think?). The API has probably changed a lot since then. I don't think I can help you with this. Sorry.

@Resington
Copy link

It's ok.... Arniebradfo, Thank you so much for your reply....

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment