Mount a signal-friendly flow canvas, then use its component instance, engine, and rendered diagram instance.
The first idea
One headless model powers every framework binding: the Angular component supplies the Angular surface, while the shared engine owns diagram behavior and the model owns diagram data.
Prerequisites
Use Angular 18.1 through 22 with the Angular packages listed below. The binding uses standalone components, so this example does not require an NgModule or a zone provider.
Install the packages
bashnpm install @grafloria/angular @angular/common @angular/core @angular/forms @angular/platform-browser @grafloria/engine @grafloria/renderer rxjs @grafloria/element
Mount a controlled canvas
DiagramCanvasComponent is the Angular front door for an editable canvas. Bind nodes and edges with Angular's two-way syntax, and give the host a height so the canvas has space to render.
tsimport { Component, signal } from '@angular/core';
import { DiagramCanvasComponent } from '@grafloria/angular';
@Component({
selector: 'app-root',
imports: [DiagramCanvasComponent],
template: `
<grafloria-diagram-canvas
[(nodes)]="nodes"
[(edges)]="edges"
[plugins]="true"
style="display: block; height: 400px"
/>
`,
})
export class AppComponent {
nodes = signal([
{ id: 'a', position: { x: 60, y: 80 }, size: { width: 180, height: 80 }, data: { label: 'Ingest' } },
{ id: 'b', position: { x: 380, y: 80 }, size: { width: 180, height: 80 }, data: { label: 'Publish' } },
]);
edges = signal([{ id: 'e1', source: 'a', target: 'b' }]);
}
The mounted canvas shows two connected nodes. [plugins]="true" adds the minimap, zoom and fit controls, and background grid; omit it when you do not want those controls. Dragging or connecting updates the controlled arrays through the two-way bindings.
Read the component and engine
Hold the mounted component with Angular's viewChild. The component exposes editing and viewport methods directly; activeEngine() gives you the engine after the view has initialized.
tsimport { Component, signal, viewChild } from '@angular/core';
import { DiagramCanvasComponent } from '@grafloria/angular';
@Component({
selector: 'app-root',
imports: [DiagramCanvasComponent],
template: `
<button type="button" (click)="undo()">Undo</button>
<button type="button" (click)="redo()">Redo</button>
<grafloria-diagram-canvas
[(nodes)]="nodes"
[(edges)]="edges"
style="display: block; height: 400px"
/>
`,
})
export class AppComponent {
readonly canvas = viewChild.required(DiagramCanvasComponent);
nodes = signal([
{ id: 'a', position: { x: 60, y: 80 }, size: { width: 180, height: 80 }, data: { label: 'Ingest' } },
{ id: 'b', position: { x: 380, y: 80 }, size: { width: 180, height: 80 }, data: { label: 'Publish' } },
]);
edges = signal([{ id: 'e1', source: 'a', target: 'b' }]);
undo(): void { void this.canvas().undo(); }
redo(): void { void this.canvas().redo(); }
fit(): void { this.canvas().fitToContent(40); }
get engine() { return this.canvas().activeEngine(); }
}
The buttons call the live canvas instance, and engine reads the engine actually in use. Read engine from ngAfterViewInit onward; before the view is mounted, no canvas engine exists.
Receive a DiagramInstance
Use GrafloriaDiagramComponent when you want the framework-agnostic rendered handle directly. Its ready output supplies a DiagramInstance after the diagram mounts.
tsimport { Component } from '@angular/core';
import { GrafloriaDiagramComponent } from '@grafloria/angular';
import type { DiagramInstance } from '@grafloria/renderer';
@Component({
selector: 'app-root',
imports: [GrafloriaDiagramComponent],
template: `
<grafloria-diagram
[spec]="spec"
(ready)="onReady($event)"
style="display: block; height: 400px"
/>
`,
})
export class AppComponent {
spec = 'flowchart TD\n Ingest --> Publish';
instance?: DiagramInstance;
onReady(instance: DiagramInstance): void {
this.instance = instance;
instance.fitView(40);
}
}
The component renders the flowchart and stores the live instance. fitView() frames its content; the same instance also exposes the model through getModel() and the engine through getEngine().
What you have
You now have a standalone Angular canvas with signal-backed node and edge state, direct access to its engine, and a DiagramInstance for generic rendering operations. Continue with How Grafloria works, custom node content, or save and restore diagrams. See the Angular live tutorial for the running version.
Was this page helpful?