Skip to content

Angular Dynamic Components

Sometimes you don't know which component to render until runtime, a plugin system, a modal service, or a form renderer driven by configuration. This lesson covers Angular's APIs for creating components dynamically.

What Are Dynamic Components?

A dynamic component is one that gets created and inserted into the DOM programmatically at runtime, rather than being declared statically in a template. Angular provides ViewContainerRef.createComponent() and the NgComponentOutlet directive for this.

Common use cases include modal/dialog services, notification/toast systems, and rendering a component chosen from a configuration object or a plugin registry.

import { Component, ViewContainerRef, inject } from '@angular/core';
import { AlertComponent } from './alert.component';

@Component({ selector: 'app-host', standalone: true, template: '<ng-container #target></ng-container>' })
export class HostComponent {
  private vcr = inject(ViewContainerRef);

  showAlert() {
    const ref = this.vcr.createComponent(AlertComponent);
    ref.setInput('message', 'Saved successfully!');
  }
}

createComponent() instantiates AlertComponent and inserts it into the DOM at the host's location; setInput() passes data into it programmatically.

Creating Components Dynamically

const componentRef = viewContainerRef.createComponent(SomeComponent);
componentRef.setInput('propertyName', value);
componentRef.instance.someMethod();
componentRef.destroy();
  • ViewContainerRef.createComponent() returns a ComponentRef giving access to the instance and its inputs.
  • setInput() is the correct, type-safe way to pass data into a dynamically created component's inputs.
  • componentRef.instance gives direct access to the component class instance for calling public methods.
  • Call componentRef.destroy() when you're done with the dynamic component to clean it up.

Dynamic Components Cheatsheet

The core APIs for programmatic component creation.

API Purpose
ViewContainerRef Represents a location in the DOM where components can be inserted
createComponent(Type) Instantiates and inserts a component
ComponentRef.setInput() Passes a value into a dynamic component's input
ComponentRef.instance Direct reference to the created component class instance
ComponentRef.destroy() Removes the component and cleans it up
NgComponentOutlet Declarative directive for rendering a component by reference in a template

Declarative Rendering With NgComponentOutlet

For simpler cases, NgComponentOutlet lets you render a dynamic component directly in a template by binding to a component class reference, no manual ViewContainerRef code required.

@Component({
  selector: 'app-widget-host',
  standalone: true,
  imports: [NgComponentOutlet],
  template: '<ng-container [ngComponentOutlet]="widgetComponent"></ng-container>',
})
export class WidgetHostComponent {
  widgetComponent = ChartWidgetComponent;
}

Cleaning Up Dynamic Components

Unlike components declared in a template, Angular does not automatically destroy dynamically created components for you until their parent view is destroyed, call componentRef.destroy() explicitly (for example, when a modal closes) to free resources promptly.

Common Mistakes

  • Forgetting to call componentRef.destroy(), leaving dynamically created components (and their subscriptions) alive indefinitely.
  • Setting inputs by assigning directly to componentRef.instance.someInput instead of using setInput(), which can bypass Angular's change detection.
  • Overusing dynamic components for cases that could be solved with a simple @if/*ngIf and a statically declared component.
  • Not handling the case where the dynamic component's host ViewContainerRef isn't yet available when open() is called.

Key Takeaways

  • Dynamic components are created programmatically with ViewContainerRef.createComponent().
  • ComponentRef.setInput() is the correct way to pass data into a dynamically created component.
  • NgComponentOutlet offers a simpler, declarative way to render a dynamic component by reference.
  • Always call destroy() on dynamically created components once they're no longer needed.

Pro Tip

Reach for NgComponentOutlet first for simple "render this component based on a variable" cases; drop down to ViewContainerRef.createComponent() only when you need full programmatic control, like a modal or toast service.