Glenn Mohammad
Glenn Mohammad

Reputation: 4715

Angular: referencing EmbeddedViewRef from a component

Quoting Angular core API docs page on EmbeddedViewRef:

An embedded view can be referenced from a component other than the hosting component whose template defines it, or it can be defined independently by a TemplateRef.

It's clear to me that for the latter I can create an EmbeddedViewRef instance from a TemplateRef instance, e.g.,

example.component.html

<p>Hip!</p>
<ng-container #vc></ng-container>
<ng-template #tpl>
  <p>Hip!</p>
</ng-template>
<p>Hooray!</p>

example.component.ts

ngAfterViewInit() {
  const embeddedView = this.tpl.createEmbeddedView(null);
  this.vc.insert(embeddedView);
}

But it still leaves me an open question about the former: how do we reference an embedded view from a component other than the hosting component whose template defines it?

Upvotes: 1

Views: 4348

Answers (1)

Reactgular
Reactgular

Reputation: 54801

An embedded view can be referenced from a component other than the hosting component whose template defines it, or it can be defined independently by a TemplateRef.

They are referring to the value of this in the template.

When you write an expression like <h1>{{value}}</h1> it is referencing the property named value on the current component. We don't prefix the expression with this, for example <h1>{{this.value}}</h1> as the context is always the component.

So when you create an embedded view from a template reference. The component that the template originates from persists to be the context for this. This is what they mean by "can be referenced from a component other than the hosting component". The fact that the view was attached to the view container of another component doesn't change the value of this in the template.

This is an import fact about embedded views that isn't clearly explained in the documentation. When you attach an embedded view to a view container of another component, then that embedded view follows the life cycle of that other component. Which means, if the original component that created the embedded view is destroyed then the embedded view continues to reference the value of this which is now a destroyed component.

You can get around this by destroying the embedded view when the component that creates it is also destroyed.

I've created a stackblitz that illustrates the issue. The "child" component creates an embedded view, and attaches it to the view container of a parent component. The embedded view references the child's properties and calls a method. This happens from the view of another component illustrating that the value of this does not change, but when the "child" is destroyed I must also destroy the embedded view.

https://stackblitz.com/edit/angular-eg4vpf

Now, go back to the stackblitz and comment out line 27 in the child.component.ts so that the view is not destroyed. See how template references continue to reference this after the app is cleared, but the components that created those templates have been destroyed. That would be a bug in the app then.

Upvotes: 2

Related Questions