Observablerxjs
Observablerxjs

Reputation: 722

Call function from generic component Angular

I am using Angular 9 and I have a data strcture as follow:
myMap: Map<key: string, value: {component: any, data: string}>

I have 3 elements in my map, the first attribute of my value object is a Component type. I use it to create dynamically new components Like:

const componentFactory = this.componentFactoryResolver.resolveComponentFactory(this.myMap.get(compName).component);
this.container.clear();
const comp = this.container.createComponent(componentFactory);

Now I want to call the function of the created component. All the components have one function in common (for example foo(string)) but implemented differently in each component. How can I call this function. I tried to do:
(<this.myMap.get(compName).component>comp.instance).foo('abcd');
However I have a compilation error.

An example of my map object:

myMap: Map<key: string, value: {component: any, data: string}> = [
    ['compA', {comp: AComponent, data: 'A'}],
    ['compB', {comp: BComponent, data: 'B'}],
    ['compC', {comp: CComponent, data: 'C'}]
]

The way I thought of doing it was with 3 if else statements like:

if (compName === 'compA') {
    (<compA>comp.instance).foo('abcd');
} else if (compName === 'compB') {
    (<compB>comp.instance).foo('abcd');
} else if (compName === 'compC') {
    (<compC>comp.instance).foo('abcd');
}

But that's really not beautiful, is there another way to do this?

Upvotes: 1

Views: 482

Answers (1)

amakhrov
amakhrov

Reputation: 3939

  1. Define an interface with your foo function:
interface WithFoo {
  foo: (s: string): void
}
  1. Implement this interface in your components:
@Component()
class CompA implements WithFoo {
  foo(s: string): void {...} 
}
  1. Update myMap with a narrow type for your component:
type MyMap = Map<string, {component: Type<WithFoo>, data: string}>;

Now

  • this.myMap.get(compName).component has a type of Type<WithFoo>
  • componentFactory has type ComponentFactory<WithFoo>
  • comp has type ComponentRef<WithFoo>
  • and finally comp.instance has type WithFoo - so you can call .foo(data) on it

Upvotes: 2

Related Questions