bhylu.com

Advertisements

Angular Dynamic Components

Dynamic component rendering chooses a component type at runtime. NgComponentOutlet is useful when the host knows where a view belongs but chooses its component implementation later.

How it works

The desk opens a detail component after a button press. The outlet receives both a component type and a deliberate input dictionary. Dynamic inputs still need to match the component’s runtime contract; the template checker cannot always prove every property relationship through an arbitrary dictionary. For imperative ownership and finer insertion control, ViewContainerRef offers a lower-level creation API.

Run the code

Use a separate empty project folder with a compatible Node version: ^22.22.3, ^24.15.0 or a supported 26+ runtime. The review uses Node 24.22.1, Angular 22.2.4, CLI/build 22.2.5 and TypeScript 6.0.3. Node 22.15.1 is too old for Angular 22. Save every download at its displayed path; browsers may keep only the basename, so recreate the src folder. Run npm install, npm run build and npm start, then open the loopback address printed by the server. Run npm test for the supplied component tests. These are local teaching projects, not Bhylu publishing files.

The small loopback server serves the compiled app and fixed, read-only tool API fixtures. It is not a database, authentication or lending service. Angular examples do not run in Bhylu’s current HTML or TypeScript playground. No Apache, MySQL or PHP configuration change is needed.

Example

src/app.ts

import { Component } from '@angular/core';
import { Type, input, signal } from '@angular/core';
import { NgComponentOutlet } from '@angular/common';
@Component({
  selector: 'bh-dynamic-components-part-0',
  standalone: true,
  template: '<p data-result>{{ name() }} details</p>',
})
class ToolDetails {
  name = input.required<string>();
}
@Component({
  selector: 'bh-dynamic-components',
  standalone: true,
  imports: [NgComponentOutlet],
  template: `<button type="button" (click)="chosen.set(Details)">Open details</button>
    @if (chosen()) {
      <ng-container *ngComponentOutlet="chosen(); inputs: values"></ng-container>
    } @else {
      <p data-result>No component selected</p>
    }`,
})
export class App {
  Details = ToolDetails;
  chosen = signal<Type<unknown> | null>(null);
  values = { name: 'Clamp' };
}

Expected result

No component selected

Opening Details creates the real ToolDetails component and supplies its required name. The review checks the resulting Clamp details text. If a component or its resources are created imperatively, the creating code must also own its destruction and provider lifetime.

Advertisements