I would like to be able to have this projected content:
<app-host>
<app-some-compA tag>...</app-some-compA>
<app-some-compB tag>...</app-some-compB>
</app-host>
And then use app-host
ViewContainerRef
to viewContainerRef.createComponent()
as many component A's and B's as I want. Is there an equivalent ComponentRef
to the TemplateRef
that I could use to read
in my content children query? Using template refs I could solve it like this:
class AppHostComponent {
@ContentChildren(TagDirective, {read: TemplateRef}) tagged: QueryList<TemplateRef>;
constructor(private readonly container: ViewContainerRef) {}
createNew() {
this.container.createEmbeddedView(this.tagged.get(0));
}
}
this is ofcourse just a minimal example, rough around the edges, but I'd like to do the same with components, instead of templates, but I don't know what I could read in the content query to use?
No, ComponentRef is already a created instance ref, BUT you can use template refs for your purpose.
Angular star syntax *someDirective
already creates a template implicitly. so you could do
@Directive({selector: '[itemTpl]'})
class ItemTplDirective { // helper directive to mark and reference the template
tpl = inject(TemplateRef);
}
class AppHostComponent {
@ContentChildren(ItemTplDirective) tagged: QueryList<ItemTplDirective>;
constructor(private readonly container: ViewContainerRef) {}
createNew() {
this.container.createEmbeddedView(this.tagged.get(0).tpl);
}
}
<app-host>
<app-some-compA *itemTpl>...</app-some-compA>
</app-host>
or a more simplistic (but less powerful) api would be to pass a component class as a property and use .createComponent
instead of .createEmbeddedView
<app-host [components]="components"/>
...
components = [ComponentAClass, ComponentBClass]