Dynamic Components

Create Components at Runtime

Dynamic Components

Use ViewContainerRef.createComponent to insert a component programmatically — useful for dialogs, popovers, and plugin systems.

4 min read Level 3/5 #angular#components#dynamic
What you'll learn
  • Inject ViewContainerRef
  • Call createComponent(MyComponent)
  • Set inputs and listen to outputs programmatically

Most components are placed declaratively in a template. Sometimes you want to spawn one at runtime — a toast, a modal, an editor plugin. That is a dynamic component.

Insert at a Location

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

@Component({
  selector: 'app-root',
  standalone: true,
  template: `<button (click)="show()">Show toast</button>`,
})
export class AppComponent {
  private vcr = inject(ViewContainerRef);

  show() {
    const ref = this.vcr.createComponent(ToastComponent);
    ref.setInput('message', 'Saved!');

    ref.instance.dismissed.subscribe(() => ref.destroy());

    setTimeout(() => ref.destroy(), 3000);
  }
}

ViewContainerRef is a marker for a position in the DOM. createComponent() returns a ComponentRef you can use to drive the instance.

Setting Inputs and Reading Outputs

  • ref.setInput('name', value) — works for both signal inputs and legacy @Input(). Triggers change detection.
  • ref.instance.someOutput.subscribe(fn) — outputs are still observable-like.
  • ref.destroy() — removes the component and runs ngOnDestroy.

Anchored ViewContainerRef

Often you want the dynamic component to land at a specific spot in your template, not at the host. Use a template anchor.

<ng-template #anchor />
import { viewChild, ViewContainerRef } from '@angular/core';

anchor = viewChild.required('anchor', { read: ViewContainerRef });

show() {
  const ref = this.anchor().createComponent(ToastComponent);
  ref.setInput('message', 'Hello');
}

This is exactly how Angular CDK Overlay and most modal libraries work under the hood.

Two Form APIs — Pick One →