Reputation: 1806
I have this simplified html structure in a template:
<div>
<grid
class="enhanced"
enhancedGrid
[infoTooltipContainer]="infoTooltipViewRef"
>
</grid>
</div>
<div #infoTooltip></div>
In the component file I read the ViewContainerRef
of the infoTooltip
div
the usual way:
@ViewChild('infoTooltip', { static: true, read: ViewContainerRef }) infoTooltipViewRef!: ViewContainerRef;
As you can see, I assign this variable to an input property, which the directive uses later.
On the grid I have in some cells simple icons. Hovering this icons a tooltip appears. The content of the tooltip can be simple string or an other component. This other component is defined the standard way (html, css, ts, module) in the file structure of the project. And there can be multiple such components. This components can be then assigned to a tooltip object. In order to assign this components to the tooltips, we have to inject this in the ts file of the grid component, f. e.:
customTooltipComp: InfoTooltipComponent = inject(InfoTooltipComponent);
And use it at declaring the tooltips, f. e.:
{
name: 'feb - 8',
columnField: 'feb',
rowField: 'id',
rowValue: 8,
icon: '<span class="material-symbols-outlined">info</span>',
content: this.customTooltipComp,
}
Now, in the directive, hovering on an icon, if the type of the content
variable isn't a string, then I want to create the provided custom component like this:
config.infoTooltipContainer.createComponent(tooltip.content);
infoTooltipContainer
is a ViewContainerRef
and has it's value from the input property of the directive (I checked it via simple console.log
).
But upon creating the custom component, I get this error in the above line:
componentFactory.create is not a function
Which I don't understand, because the infoTooltipContainer
is initialized properly (at least I think so and consoling it has also it's right value).
So, how to solve it?
Upvotes: 0
Views: 41
Reputation: 1806
Finally I found the right way to do this.
I don't need any component injection via DI like
customTooltipComp: InfoTooltipComponent = inject(InfoTooltipComponent);
Instead I only have to pass the InfoTooltipComponent
like this:
{
name: 'feb - 8',
columnField: 'feb',
rowField: 'id',
rowValue: 8,
icon: '<span class="material-symbols-outlined">info</span>',
content: InfoTooltipComponent,
}
Now, it works as expected.
Upvotes: 0
Reputation: 146
ComponentFactoryResolver
to create component factoryimport {
Directive,
Input,
ViewContainerRef,
ComponentFactoryResolver,
Type
} from '@angular/core';
@Directive({
selector: '[tooltipInjector]'
})
export class TooltipInjectorDirective {
@Input() infoTooltipContainer!: ViewContainerRef;
constructor(
private componentFactoryResolver: ComponentFactoryResolver
) {}
createDynamicTooltip(componentType: Type<any>) {
// Clear any existing components
this.infoTooltipContainer.clear();
// Create component factory
const componentFactory = this.componentFactoryResolver.resolveComponentFactory(componentType);
// Create component and inject into container
this.infoTooltipContainer.createComponent(componentFactory);
}
// If using standalone components in Angular 14+
createDynamicTooltipStandalone(componentType: Type<any>) {
this.infoTooltipContainer.clear();
this.infoTooltipContainer.createComponent(componentType);
}
}
Upvotes: 0