If I have a custom directive ParentDirective
and custom component ChildComponent
arranged like so:
<div appParent>
<app-child></app-child>
</div>
...then I can use @ContentChild
in the directive to refer to the component:
@ContentChild(ChildComponent) child: ChildComponent;
See this StackBlitz where this is working. (It logs to the console to show that the child
member is set).
However, if I change appParent into a structural directive, then the child
member is never set.
<div *appParent>
<app-child></app-child>
</div>
See this StackBlitz.
Is it not possible to use @ContentChild
with structural directives?
ViewChild is used to select an element from component's template while ContentChild is used to select projected content.
Descriptionlink. Use to get the first element or the directive matching the selector from the content DOM. If the content DOM changes, and a new child matches the selector, the property will be updated. Content queries are set before the ngAfterContentInit callback is called.
Structural directives are directives which change the DOM layout by adding and removing DOM elements. Angular provides a set of built-in structural directives (such as NgIf , NgForOf , NgSwitch and others) which are commonly used in all Angular projects.
Attribute directives modify the appearance or behavior of DOM elements. Structural directives add or remove elements from the DOM. Structural directives are one of the most powerful features of Angular, and yet they're frequently misunderstood.
I think you cannot, and that is due to the design used by angular for both type of directives. Creating a directive via TemplateRef
and injecting it via createEmbeddedView
of ViewContainerRef
generates the template as a sibling in the dom, not as a child. Therefore, Angular's injection also respects this so the child and the place of creation cannot see each other. You can draw it in your mind as an extra added layer there.
Here is the source code of the createEmbeddedView
createEmbeddedView(context: any): EmbeddedViewRef<any> {
return new ViewRef_(Services.createEmbeddedView(
this._parentView, this._def, this._def.element !.template !, context));
}
As you can see, it returns a new ViewRef
where it injects your context
.
More details here.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With