Live demo: ngdiagram.dev/templates/single-line-diagram
An Angular configurator for single-line diagrams (SLDs, also called one-line diagrams) of high-voltage electrical substations, built on ngDiagram. The symbol library targets the IEC 60617 graphical standard: 15 symbols across switchgear, transformers, measurement, protection, sources & loads, and compensation. The bundled set was curated against HV transmission work (>=110 kV), but the symbols and the node model are voltage-agnostic — MV and LV distribution work the same way.
It doubles as a reference template for building a domain-specific node editor on ngDiagram: a custom node/edge model, a generated symbol pipeline, geometry-derived junctions, and a schema-driven properties panel.
Features:
- IEC 60617 symbol library — 15 symbols in six categories, generated from QElectroTech sources by a build script
- Port-to-port wiring with ngDiagram's orthogonal routing; reshape a wire by dragging its segments, relink an endpoint to another port
- Junctions from geometry — dropping or relinking a wire onto another wire splits it and creates a junction node; connection dots are derived from positions on every render, never stored
- Rotate symbols with the on-canvas handle, snapped to 90°, on an 8 px grid
- Schema-driven properties panel — each symbol declares its fields; the panel renders them with Formly
- Export to SVG and DXF (for CAD tools) from the navbar
- Minimap, zoom toolbar, and keyboard cheat sheet; dark/light theme
Built against Angular 19.2 and ngDiagram 1.3 (see package.json); Node.js 18.19+, 20.11+ or 22 and npm 10+.
git clone https://github.com/synergycodes/ng-diagram-single-line-diagram.git
cd ng-diagram-single-line-diagram
npm install
npm startOpen http://localhost:4200 — the canvas opens on an example 220/110 kV transformer bay, with the symbol library on the left. Click a symbol to edit its properties, drag another one in from the library and wire it terminal-to-terminal, then drop a wire onto an existing one to see a junction appear. The example lives in src/app/sld/diagram/model/initial-model.ts; empty that file's placements and the canvas starts blank.
| Command | What it does |
|---|---|
npm start |
Dev server with hot reload (ng serve). |
npm run build |
Production build to dist/single-line-diagram. |
npm run watch |
Development build in watch mode. |
npm test |
Unit tests via Karma + Jasmine (npm run test:ci runs them once, headless). |
npm run build:symbols |
Regenerate the symbol registry from the QElectroTech sources. |
npm run lint |
Lint with ESLint (angular-eslint). |
npm run format |
Format with Prettier; npm run format:check verifies without writing. |
The app is a single standalone-component Angular app. The route '' lazy-loads
SldPageComponent, which hosts a header, the symbol library (left), the canvas
(center), and the properties panel (right). provideNgDiagram() is provided on
that page, not at the bootstrap root, because ngDiagram services inject the
host ElementRef.
Editing is native ngDiagram: symbol ports are visible, the user draws edges
port-to-port, and edges use ngDiagram's built-in orthogonal routing. Dropping
or relinking an edge onto another edge splits it and creates a real
sld-junction node at the meeting point. A separate overlay paints connection
dots wherever 3+ wire-continuations coincide; those dots are derived from world
positions every render and never stored, so they can't drift from the geometry.
The starting diagram in diagram/model/initial-model.ts is plain model data —
symbol placements on the 8 px grid, sized from the symbol registry, plus the
links between their terminals.
sld-symbol: an IEC 60617 device. Fixed-size body plus dynamic leads (stubs from each terminal to the body edge that fill the gap to the bounding box).sld-junction: an 8 px node with four directional ports, created and torn down automatically as edges meet.
The app uses ngDiagram's built-in shortcuts, also listed in the in-app cheat sheet (the help button on the zoom toolbar). Symbol rotation is done with the on-canvas rotate handle, snapped to 90°.
| Keys | Action |
|---|---|
Click / Ctrl+Click |
Select / add to selection. |
Shift + drag |
Box-select an area. |
Ctrl+A |
Select all. |
Delete |
Remove the selection. |
Ctrl+C / Ctrl+V |
Copy / paste. |
Ctrl + wheel |
Zoom in / out. |
Arrows |
Pan the viewport / move the selection. |
Esc |
Cancel the current gesture. |
Common extension points:
- Add a symbol. Drop a
.elmtfile intosrc/tools/qet-source/, add a stub tosrc/tools/symbols.config.mjs, then runnpm run build:symbols. Do not hand-edit the generatedsrc/app/sld/symbols/symbol-registry.generated.tsorsrc/assets/symbols/*.svg. - Add a node type. See
src/app/sld/diagram/core/geometry/node-types.tsfor the type constants and data contracts, and register the component in the template map insrc/app/sld/diagram/canvas/diagram.component.ts. - Add a properties-panel field type. Register a new Formly type in
SldPageComponent.providers, extendPropertyTypeinsrc/app/sld/symbols/types.ts, and extend the mapper insrc/app/sld/components/properties-panel/formly/field-from-property-def.ts.
src/tools/build-symbols.mjs converts a curated subset of QElectroTech .elmt
sources into SVG bodies and a TypeScript registry. It splits each device into a
fixed body and dynamic leads at build time, enforces 8 px grid alignment, and
fails loudly if a generated dimension is not a multiple of the grid.
Unit tests live next to their source as *.spec.ts and run on Karma + Jasmine.
The current suite covers the pure-function geometry, routing, and junction
logic. Run a single file with npm test -- --include='**/path/to/file.spec.ts'.
- Angular 19 — standalone components, signals
- ngDiagram (
ng-diagramon npm) — diagram rendering, viewport, selection, orthogonal routing - Formly (
@ngx-formly/core) — schema-driven properties panel - ESLint and Prettier
Architecture and per-feature guides live next to the code:
src/app/sld/diagram/README.md— the diagram subsystem:core/vsfeatures/, how a feature registers with the canvas, and the extension-point patterns (ReshapeExtension,DroppedBranch).src/app/sld/diagram/features/*/README.md— one per feature.src/app/sld/shared/icons/README.md— the icon system.
- Issues: GitHub Issues
- ngDiagram Discussions: GitHub Discussions, Discord
- ngDiagram Documentation: ngdiagram.dev/docs
This project's own code is released under the MIT License.
The electrical symbol artwork is derived from the QElectroTech elements library and is licensed under CC-BY 3.0. See NOTICE.md for attribution details and the list of derived versus project-original sources.
Built with ❤️ by the Synergy Codes team
