Skip to the solution
HardFrontend8 min read

What is the difference between ElementRef, TemplateRef, and ViewContainerRef?

691 views

The problem

Question presented to candidate: "Explain ElementRef, TemplateRef and ViewContainerRef. Then use them to write a tiny structural directive, something like *repeat="3", and tell me where the created views actually end up in the DOM."

What a strong answer should cover:

  • ElementRef: a wrapper around a rendered element, nativeElement is the real DOM node (a comment node for ng-template); the typings flag it as a security risk to use directly.
  • TemplateRef: a blueprint of an <ng-template> (or a * structural directive host) that is not rendered until someone stamps it out; injectable only where there is a template, otherwise NG0201.
  • ViewContainerRef: an anchor point where views can be inserted; createEmbeddedView(templateRef, context), createComponent(Type), clear(), length, move, indexOf.
  • Views are inserted as siblings next to the anchor (a comment node), not as children of it; createComponent on a component's own container puts the new component after its host.
  • Template context: $implicit and named values become let- variables (let n; let total = total).
  • How this relates to ngTemplateOutlet, @if / @for, and dynamic components.

Clarifying questions expected:

  • "Should the directive clean up and re-render when the count changes?"
  • "Do you want to inject them or obtain them with a query?"

Code / implementation expected: Yes β€” a structural directive with TemplateRef + ViewContainerRef, plus a directive using ElementRef.

  • components
  • views

Try it yourself

Sketch your approach before you read the solution. That is what the interview tests.

Stuck? Get a hint.

A short nudge toward the approach. It will not give the answer away.

Solution

The solution is hidden so you can try first

8 min read Β· 9 sections

Read the code

AngularA *repeat structural directive with TemplateRef and ViewContainerRef, plus ElementRef and createComponent
import { Component, Directive, ElementRef, Input, TemplateRef, ViewContainerRef, inject, signal } from "@angular/core";

// ElementRef: a wrapper around the host DOM element.
@Directive({ selector: "[showTag]" })
export class ShowTagDirective {
  constructor() {
    const el = inject(ElementRef<HTMLElement>).nativeElement;
    console.log("ElementRef.nativeElement:", el.tagName, el.constructor.name);
  }
}

// TemplateRef + ViewContainerRef: a tiny structural directive.
@Directive({ selector: "[repeat]" })
export class RepeatDirective {
  private tpl = inject(TemplateRef<{ $implicit: number; total: number }>);
  private vcr = inject(ViewContainerRef);
  @Input() set repeat(times: number) {
    this.vcr.clear();
    for (let i = 1; i <= times; i++) {
      this.vcr.createEmbeddedView(this.tpl, { $implicit: i, total: times });
    }
    console.log("ViewContainerRef.length =", this.vcr.length);
  }
}

@Component({ selector: "hello-badge", template: `<b>dynamic badge</b>` })
export class HelloBadgeComponent {}

@Component({
  selector: "app-root",
  imports: [ShowTagDirective, RepeatDirective],
  template: `
    <section id="box" showTag>
      <i *repeat="count(); let n; let total = total">{{ n }}/{{ total }}</i>
    </section>
    <button id="more" (click)="count.set(count() + 1)">more</button>
    <button id="badge" (click)="addBadge()">badge</button>`,
})
export class AppComponent {
  count = signal(2);
  private vcr = inject(ViewContainerRef); // the root host element's container
  addBadge() {
    this.vcr.createComponent(HelloBadgeComponent);
  }
}

Discussion

Other approaches, follow-ups and how it went in real interviews.

Sign in to join the discussion.

No comments yet. Share how you would answer it.

Question 97 of 121 in Angular

Keep your momentum going.

Mark this question solved to track your progress, then take the next one while it is fresh.

All Angular questions
Up nextHard

What is NgRx?

Continue