I built a config-driven graph editor for Angular — here's what I learned
Source: Dev.to
The Problem with Existing Tools
Most graph libraries fall into two camps. Either they are powerful but complex, requiring you to learn a whole new rendering paradigm, or they are simple but opinionated, forcing your data into their structure.
What I wanted was something that felt native to Angular—something that understood signals, templates, and change detection, and kept the visual representation separate from my domain logic.
Introducing @utisha/graph-editor
@utisha/graph-editor is a visual graph editor built specifically for Angular 19+. It renders with SVG, handles layout with dagre, and keeps everything reactive with signals. No RxJS, no canvas, no fuss.
The core idea is simple: you define what your nodes and edges look like through configuration, not code. The library handles panning, zooming, selection, and rendering. You focus on your data.
Quick Start
Install the package
npm install @utisha/graph-editor
Use the component
import { Component, signal } from '@angular/core';
import {
GraphEditorComponent,
Graph,
GraphEditorConfig,
} from '@utisha/graph-editor';
@Component({
selector: 'app-editor',
standalone: true,
imports: [GraphEditorComponent],
template: `
`,
})
export class EditorComponent {
/** Configuration for the editor */
config: GraphEditorConfig = {
nodes: {
types: [
{
type: 'task',
label: 'Task',
icon: '⚙️',
component: null,
defaultData: { name: 'New Task' },
size: { width: 180, height: 80 },
},
],
},
edges: {
component: null,
style: {
stroke: '#94a3b8',
strokeWidth: 2,
markerEnd: 'arrow',
},
},
canvas: {
grid: { enabled: true, size: 20, snap: true },
zoom: {
enabled: true,
min: 0.25,
max: 2,
wheelEnabled: true,
},
},
};
/** Reactive graph state */
graph = signal({
nodes: [
{
id: '1',
type: 'task',
data: { name: 'Start' },
position: { x: 100, y: 100 },
},
{
id: '2',
type: 'task',
data: { name: 'End' },
position: { x: 350, y: 100 },
},
],
edges: [{ id: 'e1', source: '1', target: '2' }],
});
}
That’s it—you now have a draggable, zoomable graph that reacts to your signal changes.
What Makes It Different
- Configuration‑driven architecture – define node types, edge styles, and themes in a single config object. Your components stay clean, your graph logic stays testable, and your domain model stays untouched.
- Built for Angular 19+ – uses signals for state management and change detection. No RxJS subscriptions, no memory‑leak worries, no
async‑pipe clutter. - SVG rendering – crisp at any zoom level, selectable text, CSS styling works out‑of‑the‑box. You can even plug in custom Angular components via
ngComponentOutlet.
Theme presets
| Theme | Description |
|---|---|
| Default | Clean white background for documentation and diagrams |
| Compact | Cool blue‑gray with dot grid for dense workflows |
| Detailed | Warm amber tones for process maps and charts |
| Dark | Charcoal background with cyan accents for developer tools |
Note: You can completely restyle the editor to match any brand. Here’s a screenshot from a proprietary app I built:
Features That Matter
- ✅ Custom node rendering with
ng-templateorngComponentOutlet - ✅ Edge path strategies: straight, bezier, step
- ✅ Undo/redo with full state history
- ✅ Multi‑select (Shift‑click or box selection)
- ✅ Node resize handles
- ✅ Auto‑layout powered by dagre
- ✅ Keyboard shortcuts (Delete, Ctrl + Z, Ctrl + Shift + Z)
- ✅ Lightweight – only Angular and dagre as dependencies
Try It Out
Live demo:
StackBlitz:
npm:
GitHub:
What I Learned
Building @utisha/graph-editor taught me how to:
- Leverage Angular signals for a truly reactive UI without the overhead of RxJS.
- Keep rendering logic (SVG) separate from domain models, making the library easy to adopt in any project.
- Provide a configuration‑first API that stays flexible yet opinionated enough to get started quickly.
Give it a spin and let me know what you think!
Building this reinforced something I already suspected: Angular's signal‑based reactivity is genuinely pleasant to work with. Building a complex interactive component without RxJS felt almost too simple. No `BehaviorSubject`, no `distinctUntilChanged`, no manual subscription cleanup. Just signals and effects, and the framework handles the rest.
The configuration‑driven approach paid off too. Early on I tried embedding node‑rendering logic directly in the component. It got messy fast. Moving to a config object with render strategies made the library flexible enough for my use case while staying simple for quick prototypes.
What’s Next
- The library is stable at v1.0.7 and ready for production use.
- I’m working on better documentation, more layout algorithms beyond Dagre, and possibly a plugin system for custom edge types.
If you’re building workflow tools, process designers, or any app that needs visual graph editing in Angular, give it a try. I built this because I needed it—maybe you do too.
- ⭐ Star the repo if you find it useful.
- 🐞 Open an issue if something breaks.
- 🤝 Pull requests are welcome.


