Angular  

Content Projection and ViewContainerRef in Angular — A Practical Developer Deep Dive

Content projection and ViewContainerRef are two of the most powerful Angular features that allow you to build flexible, reusable, and dynamic UI components.
This article takes you through both concepts with simple explanations, real-life case studies, and practical examples.

1. What Is Content Projection?

Content projection allows you to insert external content into a component’s view.
This is how Angular enables reusable UI components with customizable content (similar to slots in Web Components).

You use ng-content to mark where projected content should appear.

2. Basic Example of Content Projection

Create a reusable card component.

card.component.html

<div class="card">
  <div class="card-header">
    <ng-content select="[card-title]"></ng-content>
  </div>

  <div class="card-body">
    <ng-content></ng-content>
  </div>
</div>

Using the component

<app-card>
  <h3 card-title>Login</h3>
  <p>Please enter your email and password</p>
</app-card>

This gives you a flexible component where the parent decides what content goes inside.

3. Case Study — Building a Reusable Modal Component

This modal can accept:

  • Header content

  • Body content

  • Footer content

modal.component.html

<div class="modal">
  <div class="modal-header">
    <ng-content select="[modal-header]"></ng-content>
  </div>

  <div class="modal-body">
    <ng-content select="[modal-body]"></ng-content>
  </div>

  <div class="modal-footer">
    <ng-content select="[modal-footer]"></ng-content>
  </div>
</div>

Usage

<app-modal>
  <h2 modal-header>Confirm Delete</h2>
  <p modal-body>Are you sure?</p>
  <button modal-footer>Yes</button>
</app-modal>

This is a perfect example of "slot-based design".

4. Single Slot vs Multi-Slot Projection

Single slot

<ng-content></ng-content>

Multi-slot using selectors

<ng-content select=".header"></ng-content>
<ng-content select=".body"></ng-content>

Angular chooses the <ng-content> slot based on CSS-like selectors.

5. What Content Projection Cannot Do

Understanding limitations helps decide when to use ViewContainerRef.

Content projection cannot:

  • Dynamically create or remove components

  • Modify projected content

  • Load components based on logic

  • Insert components programmatically

For those use-cases, we use ViewContainerRef.

6. Introduction to ViewContainerRef

ViewContainerRef allows you to:

  • Dynamically create components

  • Insert or remove them at runtime

  • Control the rendering programmatically

It is commonly used with:

  • Dynamic forms

  • Dynamic modals

  • Portal-like components

  • Component factories

7. Basic Example of ViewContainerRef

Directive to mark insertion point

@Directive({
  selector: '[dynamicHost]',
})
export class DynamicHostDirective {
  constructor(public viewContainerRef: ViewContainerRef) {}
}

Component that dynamically loads another component

@Component({
  selector: 'app-dynamic-loader',
  template: `<ng-template dynamicHost></ng-template>`,
})
export class DynamicLoaderComponent implements AfterViewInit {

  @ViewChild(DynamicHostDirective, { static: true })
  host!: DynamicHostDirective;

  constructor(private resolver: ComponentFactoryResolver) {}

  ngAfterViewInit() {
    const viewContainer = this.host.viewContainerRef;
    viewContainer.clear();

    const factory = this.resolver.resolveComponentFactory(HelloComponent);
    viewContainer.createComponent(factory);
  }
}

Dynamically added component

@Component({
  selector: 'app-hello',
  template: `<p>Hello from dynamic component!</p>`,
})
export class HelloComponent {}

This displays a component without being in the template statically.

8. Case Study — Dynamic Form Builder

Many enterprise apps require:

  • Forms that change based on user role

  • Fields coming from database metadata

  • Adding/removing fields at runtime

This is where ViewContainerRef shines.

Insert dynamic input fields

addField(fieldType: any) {
  const container = this.dynamicHost.viewContainerRef;
  const componentRef = container.createComponent(fieldType);
}

You can dynamically add:

  • <input>

  • <select>

  • Custom form components
    …all loaded during runtime.

9. Content Projection vs ViewContainerRef — When to Use What

FeatureContent ProjectionViewContainerRef
Reusable layout templatesYesNo
Dynamic UI creationNoYes
Parent provides contentYesNo
Programmatic controlNoYes
Better forCards, modals, tabs, layoutsDynamic forms, dynamic pages
Managed byTemplateComponent code

Rule of Thumb

  • If you know the structure at compile time → Use ng-content

  • If the structure changes at runtime → Use ViewContainerRef

10. Combining Both (Real Enterprise Example)

You want:

  • Tabs with custom content (projection)

  • Each tab dynamically loads a component when selected (ViewContainerRef)

This gives:

  • Performance (lazy loading)

  • Flexibility (content projection)

  • Dynamic rendering

11. Best Practices

Content Projection

  • Use select for multi-slot structure

  • Avoid deeply nested ng-content

  • Use it for visual flexibility, not dynamic behavior

ViewContainerRef

  • Always call .clear() before creating components

  • Remove views when navigation changes

  • Prefer Angular’s newer API createComponent() instead of old ComponentFactoryResolver

  • Use ng-template with a directive to mark insertion points

12. Summary

Content Projection is used for static but flexible templates, while ViewContainerRef is used for dynamic component rendering.

Together, they help you build:

  • Highly reusable UI components

  • Dynamic dashboards

  • Form builders

  • Modal systems

  • Enterprise-level UI frameworks