Skip to content

Angular

Terminal window
npm install @kadal/deck-angular @angular/core @angular/compiler @angular/platform-browser
src/main.tsx
registerLazyRenderer("angular", () => import("@kadal/deck-angular").then((m) => m.angularRenderer));
chart.angular.ts
import "@angular/compiler"; // must be the FIRST import
import { Component, Input } from "@angular/core";
import { deckAngular } from "@kadal/deck-angular";
@Component({ selector: "deck-chart", standalone: true, template: `…` })
export class Chart {
@Input() data: number[] = [];
}
deckAngular(Chart);
<Island load={() => import("./chart.angular.ts").then((m) => m.Chart)} props={{ data }} />

The deck’s tsconfig needs experimentalDecorators: true and useDefineForClassFields: false. That is the whole build configuration — no Angular Vite plugin.

  1. No Analog plugin. Pointed at one file in a deck it emitted an empty module, and the island sat on its fallback with no error. Importing @angular/compiler (JIT) needs no plugin at all.
  2. import "@angular/compiler" first. It registers the compiler facade, which @angular/platform-browser reads the instant it is evaluated.
  3. Signal inputs need AOT — use @Input(). Under JIT, input() mounts fine and then setInput fails with NG0303, freezing the island at its first props. Internal state can still be a signal().
  4. setInput, never instance.x = y. Only setInput marks the view dirty.

Angular expects to be an application, so the renderer creates one Angular application, shared by every Angular island on the deck and destroyed when the last one leaves. It is zoneless: zone.js would patch every async API on the page for one island’s sake.