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:

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:

For those use-cases, we use ViewContainerRef.

6. Introduction to ViewContainerRef

ViewContainerRef allows you to:

It is commonly used with:

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:

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:

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

10. Combining Both (Real Enterprise Example)

You want:

This gives:

11. Best Practices

Content Projection

ViewContainerRef

12. Summary

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

Together, they help you build: