Angular: How to Render a Template for the Parent in a Child Component

using only a clean declarative approach

🪄 OZ 🎩
2 min readOct 19, 2023
“Flaming June”, Frederic Leighton, 1895
“Flaming June”, Frederic Leighton, 1895

It is a small article, just to demonstrate to you a trick that can be useful, and its implementation is not so obvious.

Problem

You have a component, that has a child component. For some reason, the child component knows better how to render one thing, and that thing should be actually part of the parent component.

Example 1:

You have a “window” component, that can contain many different components inside, but only they can know what menu items that window should have.

Example 2:

Your parent component is a list, and every child component encapsulates the state for the list item. Depending on the state, different actions are applicable to the item, and the parent should render a specific set of action buttons for every item.

Provided

We can render an <ng-template> in our child component — that’s an easy part. The only issue is how to “transfer” that template to the parent.

Solution

Angular component decorator has one not-so-popular field, exportAs.

We can use it to get access to the component instance. And while we have this access, we can use every public field and method of that component in our template.

@Component({
selector: `x-child`,
standalone: true,
exportAs: 'smartChild',
template: `
<div>Some child's content</div>
<ng-template #menuItems>
<button class="menu-item">Item 1</button>
<button class="menu-item">Item 2</button>
</ng-template>
`
})
export class ChildComponent {
@ViewChild('menuItems') menuItems: TemplateRef<any> | null = null;
}

This component has one public field: menuItems and one unusual field in its decorator: exportAs: 'smartChild'.

@Component({
selector: 'x-parent',
standalone: true,
imports: [ChildComponent, NgTemplateOutlet],
template: `
<div class="sophisticated-container">
<div class="menu-can-be-placed-only-as-direct-child">
<ng-container *ngTemplateOutlet="child.menuItems"></ng-container>
</div>
<x-child #child="smartChild"/>
</div>
`
})
export class ParentComponent {}

And that’s how we can use it in a parent:

  • we render the child component and assign its component instance to a variable #child;
  • in another part of our parent component, we use ng-container (to avoid additional DOM node) and *ngTemplateOutlet directive to output the template;
  • we can access every public field of the child component instance, so we can use child.menuItems to access the template, rendered by the child component. It is possible because the public field menuItems of our child component has a decorator ViewChild pointing to the <ng-template> in the child components’ template.

--

--