Menu
×
   ❮     
HTML CSS JAVASCRIPT SQL PYTHON JAVA PHP HOW TO W3.CSS C C++ C# BOOTSTRAP REACT MYSQL JQUERY EXCEL XML DJANGO NUMPY PANDAS NODEJS DSA TYPESCRIPT ANGULAR ANGULARJS GIT POSTGRESQL MONGODB ASP AI R GO KOTLIN SASS VUE GEN AI SCIPY CYBERSECURITY DATA SCIENCE INTRO TO PROGRAMMING BASH RUST

Angular Dynamic Components


Create components at runtime with createComponent(), or render selectorless standalone components with *ngComponentOutlet.


Dynamic Components Essentials

  • createComponent(): Create components at runtime and pass inputs, outputs, and directives directly.
  • Selectorless components: Standalone components can be used without a selector via *ngComponentOutlet.
  • Signals: Drive dynamic state from signal() and read in templates by calling the signal.

Notes:

  • Related: See Control Flow for @if/@for, and Signals for state and effects.
  • Prefer selectorless + *ngComponentOutlet for simple outlets; use createComponent() for fine-grained control (host element, directives, lifecycle).

createComponent() with inputs & outputs

  • Provide inputs/outputs and an optional hostElement to attach into the DOM.
  • Use EnvironmentInjector (or inject()) so the component can resolve providers.

Example

import { bootstrapApplication } from '@angular/platform-browser';
import { Component, EventEmitter, Output, Input, ElementRef, ViewChild, inject, EnvironmentInjector, ComponentRef } from '@angular/core';
import { createComponent } from '@angular/core';

@Component({
  standalone: true,
  template: `
    <div style="padding:8px;border:1px solid #ddd;border-radius:6px;">
      <h4 style="margin:0 0 8px 0;">{{ title }}</h4>
      <button (click)="clicked.emit()">Click</button>
    </div>
  `
})
export class Card {
  @Input() title = 'Card';
  @Output() clicked = new EventEmitter<void>();
}

@Component({
  selector: 'app-root',
  standalone: true,
  template: `
    <h3>Dynamic createComponent()</h3>
    <div #host style="min-height:60px;border:1px dashed #aaa;padding:8px;border-radius:6px;"></div>
    <div style="margin-top:8px;display:flex;gap:8px;flex-wrap:wrap;">
      <button (click)="mount()">Mount</button>
      <button (click)="update()">Update input</button>
      <button (click)="unmount()">Unmount</button>
    </div>
  `
})
export class App {
  @ViewChild('host', { read: ElementRef }) host!: ElementRef<HTMLElement>;
  env: EnvironmentInjector = inject(EnvironmentInjector);
  ref: ComponentRef<Card> | null = null;

  mount() {
    if (this.ref) return;
    this.ref = createComponent(Card, {
      environmentInjector: this.env,
      hostElement: this.host.nativeElement
    });
    this.ref.setInput?.('title', 'Hello from Dynamic');
    this.ref.instance.clicked.subscribe(() => alert('Card clicked'));
  }
  update() {
    if (!this.ref) return;
    this.ref.setInput?.('title', 'Updated Title ' + new Date().toLocaleTimeString());
  }
  unmount() {
    this.ref?.destroy();
    this.ref = null;
  }
}

bootstrapApplication(App);
<app-root></app-root>

Run Example »

Example explained

  • createComponent(Card, ...): Creates the Card component at runtime and returns a component ref.
  • environmentInjector: Supplies DI so the dynamic component can resolve providers.
  • hostElement: Attaches the component's host into the given DOM element (#host).
  • inputs/outputs: Sets initial inputs and wires output callbacks (e.g., clicked).
  • setInput / destroy: Update inputs later with ref.setInput(...) and clean up via ref.destroy().

Notes:

  • Cleanup: Always call destroy() on the component ref when removing it.
  • Updating inputs: Use setInput(name, value) on the component ref to push new input values.

REMOVE ADS


Selectorless via *ngComponentOutlet

  • Render a standalone component without a selector using *ngComponentOutlet.
  • Pass inputs and outputs inline in the outlet micro-syntax.

Example

import { bootstrapApplication } from '@angular/platform-browser';
import { Component, EventEmitter, Output, Input, signal } from '@angular/core';
import { NgComponentOutlet } from '@angular/common';

@Component({
  standalone: true,
  template: `<button (click)="clicked.emit()">{{ label }}</button>`
})
export class ActionButton {
  @Input() label = 'Do it';
  @Output() clicked = new EventEmitter<void>();
}

@Component({
  selector: 'app-root',
  standalone: true,
  imports: [NgComponentOutlet],
  template: `
    <h3>Selectorless via *ngComponentOutlet</h3>
    <p>Clicks: {{ clicks() }}</p>
    <ng-container *ngComponentOutlet="ActionButton; inputs: { label: 'Launch' }; outputs: { clicked: onClick }"></ng-container>
  `
})
export class App {
  ActionButton = ActionButton;
  clicks = signal(0);
  onClick = () => this.clicks.update(n => n + 1);
}

bootstrapApplication(App);
<app-root></app-root>

Run Example »

Example explained

  • *ngComponentOutlet="ActionButton": Renders the standalone component class referenced by ActionButton.
  • inputs / outputs: Pass values and event handlers directly in the outlet micro-syntax.
  • Signals for state: The clicks signal holds state and updates the UI when onClick increments it.

Notes:

  • Inputs/Outputs: The outlet micro-syntax supports inputs and outputs bags for easy wiring.
  • Composition: Use outlets inside @if/@for for conditional or repeated dynamic UIs.


×

Contact Sales

If you want to use W3Schools services as an educational institution, team or enterprise, send us an e-mail:
sales@w3schools.com

Report Error

If you want to report an error, or if you want to make a suggestion, send us an e-mail:
help@w3schools.com

W3Schools is optimized for learning and training. Examples might be simplified to improve reading and learning. Tutorials, references, and examples are constantly reviewed to avoid errors, but we cannot warrant full correctness of all content. While using W3Schools, you agree to have read and accepted our terms of use, cookie and privacy policy.

Copyright 1999-2025 by Refsnes Data. All Rights Reserved. W3Schools is Powered by W3.CSS.