DEV Community

Cover image for Angular: How to Render a Template for the Parent in a Child Component
Evgeniy OZ
Evgeniy OZ

Posted on • Originally published at Medium

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

...using only a clean declarative approach

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;
    }
Enter fullscreen mode Exit fullscreen mode

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 {}
Enter fullscreen mode Exit fullscreen mode

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.

🪽 Do you like this article? Share it and let it fly! 🛸

💙 If you enjoy my articles, consider following me on Twitter, and/or subscribing to receive my new articles by email.

Top comments (0)