Under The Hood
frontend angular Angular 17+

TemplateRef & ViewContainerRef: Manual View Hosting

Last updated
Prerequisites:
Angular directives and *ngIf/*ngFor
Understanding of templates and views
  • angular
  • structural-directives
  • TemplateRef
  • ViewContainerRef
  • directives

Read at your depth

The practical view

A structural directive (one with * prefix, like *myIf) is sugar for: <ng-template myIf [myIf]="cond">...</ng-template>. Inside the directive you inject TemplateRef (the ng-template content) and ViewContainerRef (the anchor where the view should be created). Then: if (cond) { this.vcr.createEmbeddedView(this.tpl); } else { this.vcr.clear(); }. This is exactly how ngIf/ngFor are implemented. You can also create dynamic components with this.vcr.createComponent(ComponentType). TemplateRef gives you the template's context (via createEmbeddedView(context)), so directives can pass data into the template.

The same idea in other frameworks

react equivalent
React render props / children-as-function and portals are the conceptual analogues.

Legacy vs modern

Repeating boilerplate with ngIf vs a custom structural directive

Hand-rolling permission checks with ngIf everywhere is repetitive; a custom structural directive encapsulates the logic and reuses the template.

before → after
Repeated ngIf permission checks
@if (auth.can('admin')) { <admin-panel /> } <!-- ❌ OLD: repeated in every template -->
Custom *hasPermission structural directive
@if true, render template via TemplateRef/ViewContainerRef — wrapped in *hasPermission="'admin'"

Interview gotchas

Context

This tests the core mental model of structural directives — the ng-template desugaring and the two-primitive contract. Interviewers want the compiler expansion, not just 'it renders templates'.

The mechanical answer

The * prefix is compiler sugar: *myDirective="expr" expands to <ng-template myDirective="expr">...</ng-template> with the directive as the host on the ng-template element. Inside the directive, TemplateRef is the handle to that embedded template (the content the user wrote inside the * element), and ViewContainerRef is the container anchored at the host's location in the parent view. Rendering requires both: TemplateRef holds the template function + declaration view, and ViewContainerRef provides the location to insert the instantiated embedded view and manages its lifecycle (create/remove/destroy). Without ViewContainerRef you have no insertion point; without TemplateRef you have nothing to render. Together they give the directive full control over when and where content appears.

Trap

The naive answer is 'the * just makes a component render conditionally'. The * compiles to an ng-template + a directive hosting it. Another trap: thinking createEmbeddedView re-runs the template function on every CD — the view is created once and its bindings update reactively; creating it repeatedly without clearing leaks views. Candidates who describe the ng-template expansion and the insert/destroy lifecycle show real understanding.

Under The Hood — a multi-depth technical interview hub.

Third-party licenses Press ⌘ K to search.